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="/modal">Modal</router-link></li>
<li><router-link to="/message">Message</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="/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> </ul>
</nav> </nav>
<router-view></router-view> <router-view></router-view>

View file

@ -180,6 +180,14 @@ const router = new VueRouter({
{ {
path: '/notice', path: '/notice',
component: require('./routers/notice.vue') 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> <template>
<div style="width: 400px;"> <Cascader :data="data4" :load-data="loadData"></Cascader>
<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>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
data: [{ data4: [
value: 'beijing', {
label: '北京', value: 'beijing',
children: [ label: '北京',
{ children: [],
value: 'gugong', loading: false
label: '故宫' },
}, {
{ value: 'hangzhou',
value: 'tiantan', label: '杭州',
label: '天坛' children: [],
}, loading:false
{ }
value: 'wangfujing', ]
label: '王府井' }
} },
] methods: {
}, { loadData (item, callback) {
value: 'jiangsu', item.loading = true;
label: '江苏', setTimeout(() => {
children: [ console.log(1)
{ if (item.value === 'beijing') {
value: 'nanjing', item.children = [
label: '南京', // {
children: [ // value: 'talkingdata',
{ // label: 'TalkingData'
value: 'fuzimiao', // },
label: '夫子庙', // {
} // value: 'baidu',
] // label: ''
}, // },
{ // {
value: 'suzhou', // value: 'sina',
label: '苏州', // label: ''
children: [ // }
{ ];
value: 'zhuozhengyuan', } else if (item.value === 'hangzhou') {
label: '拙政园', item.children = [
}, {
{ value: 'ali',
value: 'shizilin', label: '阿里巴巴'
label: '狮子林', },
} {
] value: '163',
} label: '网易'
], }
}], ];
value3: [] }
item.loading = false;
callback();
}, 1000);
} }
} }
} }

View file

@ -1,7 +1,15 @@
<template> <template>
<div> <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-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> </Checkbox-group>
<div>{{ fruit }}</div> <div>{{ fruit }}</div>
</div> </div>
@ -12,7 +20,9 @@
return { return {
social: ['facebook', 'github'], social: ['facebook', 'github'],
fruit: ['苹果'], fruit: ['苹果'],
tags: [] tags: [],
testValue1: null,
testValue2: null
} }
}, },
mounted () { 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> <div>
<Date-picker transfer type="daterange" placeholder="选择日期" style="width: 200px"></Date-picker> <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="daterange" placeholder="选择日期" style="width: 200px"></Date-picker> <Date-picker type="datetimerange" placeholder="选择日期" style="width: 200px" @on-change="changeDate"></Date-picker>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
methods: {
changeDate(date){
console.log(date);
}
}
} }
</script> </script>

View file

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

View file

@ -1,8 +1,26 @@
<template> <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> </template>
<script> <script>
export default { export default {
data () {
return {
current: 1,
total: 21
}
},
methods: {
subject() {
this.total -= 1;
},
change() {
this.current = 1;
}
}
} }
</script> </script>

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
{ {
"name": "iview", "name": "iview",
"version": "2.0.0", "version": "2.1.0",
"title": "iView", "title": "iView",
"description": "A high quality UI components Library with Vue.js", "description": "A high quality UI components Library with Vue.js",
"homepage": "http://www.iviewui.com", "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> <script>
import Casitem from './casitem.vue'; import Casitem from './casitem.vue';
import Emitter from '../../mixins/emitter'; import Emitter from '../../mixins/emitter';
import { findComponentUpward } from '../../utils/assist'; import { findComponentUpward, findComponentDownward } from '../../utils/assist';
let key = 1; let key = 1;
@ -67,7 +67,9 @@
if (fromUser) { if (fromUser) {
cascader.isLoadedChildren = true; cascader.isLoadedChildren = true;
} }
this.handleTriggerItem(item); if (item.children.length) {
this.handleTriggerItem(item);
}
}); });
return; return;
} }
@ -84,6 +86,14 @@
changeOnSelect: this.changeOnSelect, changeOnSelect: this.changeOnSelect,
fromInit: fromInit fromInit: fromInit
}); });
// #1553
if (this.changeOnSelect) {
const Caspanel = findComponentDownward(this, 'Caspanel');
if (Caspanel) {
Caspanel.$emit('on-clear', true);
}
}
} else { } else {
this.sublist = []; this.sublist = [];
this.dispatch('Cascader', 'on-result-change', { 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.sublist = [];
this.tmpItem = {}; this.tmpItem = {};
if (deep) {
const Caspanel = findComponentDownward(this, 'Caspanel');
if (Caspanel) {
Caspanel.$emit('on-clear', true);
}
}
}); });
} }
}; };

View file

@ -36,7 +36,15 @@
default: false default: false
}, },
value: { value: {
type: Boolean, type: [String, Number, Boolean],
default: false
},
trueValue: {
type: [String, Number, Boolean],
default: true
},
falseValue: {
type: [String, Number, Boolean],
default: false default: false
}, },
label: { label: {
@ -102,21 +110,26 @@
const checked = event.target.checked; const checked = event.target.checked;
this.currentValue = checked; this.currentValue = checked;
this.$emit('input', checked);
let value = checked ? this.trueValue : this.falseValue;
this.$emit('input', value);
if (this.group) { if (this.group) {
this.parent.change(this.model); this.parent.change(this.model);
} else { } else {
this.$emit('on-change', checked); this.$emit('on-change', value);
this.dispatch('FormItem', 'on-form-change', checked); this.dispatch('FormItem', 'on-form-change', value);
} }
}, },
updateModel () { updateModel () {
this.currentValue = this.value; this.currentValue = this.value === this.trueValue;
} }
}, },
watch: { watch: {
value () { value (val) {
if (val !== this.trueValue && val !== this.falseValue) {
throw 'Value should be trueValue or falseValue.';
}
this.updateModel(); 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> <template>
<div :class="classes"> <div :class="classes">
<div :class="[prefixCls+ '-list']" ref="hours"> <div :class="[prefixCls+ '-list']" ref="hours">
<ul :class="[prefixCls + '-ul']" @click="handleClickHours"> <ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="(item, index) in hoursList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li> <li :class="getCellCls(item)" v-for="item in hoursList" v-show="!item.hide" @click="handleClick('hours', item)">{{ formatTime(item.text) }}</li>
</ul> </ul>
</div> </div>
<div :class="[prefixCls+ '-list']" ref="minutes"> <div :class="[prefixCls+ '-list']" ref="minutes">
<ul :class="[prefixCls + '-ul']" @click="handleClickMinutes"> <ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="(item, index) in minutesList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li> <li :class="getCellCls(item)" v-for="item in minutesList" v-show="!item.hide" @click="handleClick('minutes', item)">{{ formatTime(item.text) }}</li>
</ul> </ul>
</div> </div>
<div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds"> <div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds">
<ul :class="[prefixCls + '-ul']" @click="handleClickSeconds"> <ul :class="[prefixCls + '-ul']">
<li :class="getCellCls(item)" v-for="(item, index) in secondsList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li> <li :class="getCellCls(item)" v-for="item in secondsList" v-show="!item.hide" @click="handleClick('seconds', item)">{{ formatTime(item.text) }}</li>
</ul> </ul>
</div> </div>
</div> </div>
@ -41,10 +41,15 @@
showSeconds: { showSeconds: {
type: Boolean, type: Boolean,
default: true default: true
},
steps: {
type: Array,
default: () => []
} }
}, },
data () { data () {
return { return {
spinerSteps: [1, 1, 1].map((one, i) => Math.abs(this.steps[i]) || one),
prefixCls: prefixCls, prefixCls: prefixCls,
compiled: false compiled: false
}; };
@ -60,6 +65,7 @@
}, },
hoursList () { hoursList () {
let hours = []; let hours = [];
const step = this.spinerSteps[0];
const hour_tmpl = { const hour_tmpl = {
text: 0, text: 0,
selected: false, selected: false,
@ -67,7 +73,7 @@
hide: false hide: false
}; };
for (let i = 0; i < 24; i++) { for (let i = 0; i < 24; i += step) {
const hour = deepCopy(hour_tmpl); const hour = deepCopy(hour_tmpl);
hour.text = i; hour.text = i;
@ -83,6 +89,7 @@
}, },
minutesList () { minutesList () {
let minutes = []; let minutes = [];
const step = this.spinerSteps[1];
const minute_tmpl = { const minute_tmpl = {
text: 0, text: 0,
selected: false, selected: false,
@ -90,7 +97,7 @@
hide: false hide: false
}; };
for (let i = 0; i < 60; i++) { for (let i = 0; i < 60; i += step) {
const minute = deepCopy(minute_tmpl); const minute = deepCopy(minute_tmpl);
minute.text = i; minute.text = i;
@ -101,11 +108,11 @@
if (this.minutes === i) minute.selected = true; if (this.minutes === i) minute.selected = true;
minutes.push(minute); minutes.push(minute);
} }
return minutes; return minutes;
}, },
secondsList () { secondsList () {
let seconds = []; let seconds = [];
const step = this.spinerSteps[2];
const second_tmpl = { const second_tmpl = {
text: 0, text: 0,
selected: false, selected: false,
@ -113,7 +120,7 @@
hide: false hide: false
}; };
for (let i = 0; i < 60; i++) { for (let i = 0; i < 60; i += step) {
const second = deepCopy(second_tmpl); const second = deepCopy(second_tmpl);
second.text = i; second.text = i;
@ -138,24 +145,11 @@
} }
]; ];
}, },
handleClickHours (event) { handleClick (type, cell) {
this.handleClick('hours', event); if (cell.disabled) return;
}, const data = {};
handleClickMinutes (event) { data[type] = cell.text;
this.handleClick('minutes', event); this.$emit('on-change', data);
},
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);
}
this.$emit('on-pick-click'); this.$emit('on-pick-click');
}, },
scroll (type, index) { scroll (type, index) {
@ -183,20 +177,24 @@
}, },
formatTime (text) { formatTime (text) {
return text < 10 ? '0' + text : 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: { watch: {
hours (val) { hours (val) {
if (!this.compiled) return; if (!this.compiled) return;
this.scroll('hours', val); this.scroll('hours', this.getItemIndex('hours', val));
}, },
minutes (val) { minutes (val) {
if (!this.compiled) return; if (!this.compiled) return;
this.scroll('minutes', val); this.scroll('minutes', this.getItemIndex('minutes', val));
}, },
seconds (val) { seconds (val) {
if (!this.compiled) return; if (!this.compiled) return;
this.scroll('seconds', val); this.scroll('seconds', this.getItemIndex('seconds', val));
} }
}, },
mounted () { mounted () {
@ -204,4 +202,4 @@
this.$nextTick(() => this.compiled = true); this.$nextTick(() => this.compiled = true);
} }
}; };
</script> </script>

View file

@ -6,6 +6,7 @@
<time-spinner <time-spinner
ref="timeSpinner" ref="timeSpinner"
:show-seconds="showSeconds" :show-seconds="showSeconds"
:steps="steps"
:hours="hours" :hours="hours"
:minutes="minutes" :minutes="minutes"
:seconds="seconds" :seconds="seconds"
@ -39,6 +40,12 @@
name: 'TimePicker', name: 'TimePicker',
mixins: [ Mixin, Locale ], mixins: [ Mixin, Locale ],
components: { TimeSpinner, Confirm }, components: { TimeSpinner, Confirm },
props: {
steps: {
type: Array,
default: () => []
}
},
data () { data () {
return { return {
prefixCls: prefixCls, prefixCls: prefixCls,
@ -113,4 +120,4 @@
if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true; if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
} }
}; };
</script> </script>

View file

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

View file

@ -1,3 +1,4 @@
import Vue from 'vue';
import Picker from '../picker.vue'; import Picker from '../picker.vue';
import DatePanel from '../panel/date.vue'; import DatePanel from '../panel/date.vue';
import DateRangePanel from '../panel/date-range.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 Picker from '../picker.vue';
import TimePanel from '../panel/time.vue'; import TimePanel from '../panel/time.vue';
import TimeRangePanel from '../panel/time-range.vue'; import TimeRangePanel from '../panel/time-range.vue';
@ -21,6 +22,10 @@ export default {
}, },
default: 'time' default: 'time'
}, },
steps: {
type: Array,
default: () => []
},
value: {} value: {}
}, },
created () { created () {
@ -31,6 +36,11 @@ export default {
this.currentValue = ''; 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> <template>
<div :class="classes"> <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"> <div :class="[prefixCls + '-content']" :style="contentStyles">
<slot></slot> <slot></slot>
<transition name="fade"> <transition name="fade">
@ -177,6 +177,7 @@
callback(this.validateMessage); callback(this.validateMessage);
}); });
this.validateDisabled = false;
}, },
resetField () { resetField () {
this.validateState = ''; this.validateState = '';

View file

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

View file

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

View file

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

View file

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

View file

@ -71,7 +71,7 @@
// init checked status // init checked status
function reverseChecked(data) { function reverseChecked(data) {
if (!data.nodeKey) data.nodeKey = key++; if (!data.nodeKey) data.nodeKey = key++;
if (data.children) { if (data.children && data.children.length) {
let checkedLength = 0; let checkedLength = 0;
data.children.forEach(node => { data.children.forEach(node => {
if (node.children) node = reverseChecked(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 Affix from './components/affix';
import Alert from './components/alert'; import Alert from './components/alert';
import Avatar from './components/avatar';
import BackTop from './components/back-top'; import BackTop from './components/back-top';
import Badge from './components/badge'; import Badge from './components/badge';
import Breadcrumb from './components/breadcrumb'; import Breadcrumb from './components/breadcrumb';
@ -13,6 +14,7 @@ import Cascader from './components/cascader';
import Checkbox from './components/checkbox'; import Checkbox from './components/checkbox';
import Circle from './components/circle'; import Circle from './components/circle';
import Collapse from './components/collapse'; import Collapse from './components/collapse';
import ColorPicker from './components/color-picker';
import DatePicker from './components/date-picker'; import DatePicker from './components/date-picker';
import Dropdown from './components/dropdown'; import Dropdown from './components/dropdown';
import Form from './components/form'; import Form from './components/form';
@ -49,6 +51,7 @@ import locale from './locale';
const iview = { const iview = {
Affix, Affix,
Alert, Alert,
Avatar,
BackTop, BackTop,
Badge, Badge,
Breadcrumb, Breadcrumb,
@ -63,6 +66,10 @@ const iview = {
Checkbox, Checkbox,
CheckboxGroup: Checkbox.Group, CheckboxGroup: Checkbox.Group,
iCircle: Circle, iCircle: Circle,
Col,
iCol: Col,
Collapse,
ColorPicker,
DatePicker, DatePicker,
Dropdown, Dropdown,
DropdownItem: Dropdown.Item, DropdownItem: Dropdown.Item,
@ -70,9 +77,6 @@ const iview = {
Form, Form,
iForm: Form, iForm: Form,
FormItem: Form.Item, FormItem: Form.Item,
Col,
iCol: Col,
Collapse,
Icon, Icon,
Input, Input,
iInput: 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 { export default {
i: { i: {
select: { select: {
placeholder: 'Chọn', placeholder: 'Chọn',
noMatch: 'Không tìm thấy', noMatch: 'Không tìm thấy',
loading: 'Đang tải' loading: 'Đang tải'
}, },
table: { table: {
noDataText: 'Không có dữ liệu', noDataText: 'Không có dữ liệu',
noFilteredDataText: 'Không có dữ liệu lọc', noFilteredDataText: 'Không có dữ liệu lọc',
confirmFilter: 'Xác nhận', confirmFilter: 'Xác nhận',
resetFilter: 'Làm lại', resetFilter: 'Làm lại',
clearFilter: 'Xóa hết' clearFilter: 'Xóa hết'
}, },
datepicker: { datepicker: {
selectDate: 'Chọn ngày', selectDate: 'Chọn ngày',
selectTime: 'Chọn giờ', selectTime: 'Chọn giờ',
startTime: 'Ngày bắt đầu', startTime: 'Ngày bắt đầu',
endTime: 'Ngày kết thúc', endTime: 'Ngày kết thúc',
clear: 'Xóa', clear: 'Xóa',
ok: 'Đồng ý', ok: 'Đồng ý',
month: '', month: '',
month1: 'Tháng 1', month1: 'Tháng 1',
month2: 'Tháng 2', month2: 'Tháng 2',
month3: 'Tháng 3', month3: 'Tháng 3',
month4: 'Tháng 4', month4: 'Tháng 4',
month5: 'Tháng 5', month5: 'Tháng 5',
month6: 'Tháng 6', month6: 'Tháng 6',
month7: 'Tháng 7', month7: 'Tháng 7',
month8: 'Tháng 8', month8: 'Tháng 8',
month9: 'Tháng 9', month9: 'Tháng 9',
month10: 'Tháng 10', month10: 'Tháng 10',
month11: 'Tháng 11', month11: 'Tháng 11',
month12: 'Tháng 12', month12: 'Tháng 12',
year: '', year: '',
weeks: { weeks: {
sun: 'CN', sun: 'CN',
mon: 'T2', mon: 'T2',
tue: 'T3', tue: 'T3',
wed: 'T4', wed: 'T4',
thu: 'T5', thu: 'T5',
fri: 'T6', fri: 'T6',
sat: 'T7' sat: 'T7'
}, },
months: { months: {
m1: 'Th.1', m1: 'Th.1',
m2: 'Th.2', m2: 'Th.2',
m3: 'Th.3', m3: 'Th.3',
m4: 'Th.4', m4: 'Th.4',
m5: 'Th.5', m5: 'Th.5',
m6: 'Th.6', m6: 'Th.6',
m7: 'Th.7', m7: 'Th.7',
m8: 'Th.8', m8: 'Th.8',
m9: 'Th.9', m9: 'Th.9',
m10: 'Th.10', m10: 'Th.10',
m11: 'Th.11', m11: 'Th.11',
m12: 'Th.12' m12: 'Th.12'
} }
}, },
transfer: { transfer: {
titles: { titles: {
source: 'Nguồn', source: 'Nguồn',
target: 'Đích' target: 'Đích'
}, },
filterPlaceholder: 'Nhập từ khóa', filterPlaceholder: 'Nhập từ khóa',
notFoundText: 'Không tìm thấy' notFoundText: 'Không tìm thấy'
}, },
modal: { modal: {
okText: 'Đồng ý', okText: 'Đồng ý',
cancelText: 'Hủy bỏ' cancelText: 'Hủy bỏ'
}, },
poptip: { poptip: {
okText: 'Đồng ý', okText: 'Đồng ý',
cancelText: 'Hủy bỏ' cancelText: 'Hủy bỏ'
}, },
page: { page: {
prev: 'Trang trước', prev: 'Trang trước',
next: 'Trang kế', next: 'Trang kế',
total: 'Tổng', total: 'Tổng',
item: 'kết quả', item: 'kết quả',
items: 'kết quả', items: 'kết quả',
prev5: '5 trang trước', prev5: '5 trang trước',
next5: '5 trang kế', next5: '5 trang kế',
page: '/trang', page: '/trang',
goto: 'Tới trang', goto: 'Tới trang',
p: '' p: ''
}, },
rate: { rate: {
star: 'Sao', star: 'Sao',
stars: 'Sao' stars: 'Sao'
}, },
tree: { tree: {
emptyText: 'Không có dữ liệu' 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

@ -38,4 +38,6 @@
@import "carousel"; @import "carousel";
@import "rate"; @import "rate";
@import "upload"; @import "upload";
@import "tree"; @import "tree";
@import "avatar";
@import "color-picker";

View file

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

View file

@ -161,4 +161,15 @@
@slider-margin : 16px 0; @slider-margin : 16px 0;
@slider-button-wrap-size : 18px; @slider-button-wrap-size : 18px;
@slider-button-wrap-offset : -4px; @slider-button-wrap-offset : -4px;
@slider-disabled-color : #ccc; @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();
});
});
});