Commit f9508bf1785473960658c36898e41e5cb753863e

Authored by TabEnter
2 parents 75798f5b b6bda1dc

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

examples/app.vue
... ... @@ -54,6 +54,8 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
54 54 <li><router-link to="/modal">Modal</router-link></li>
55 55 <li><router-link to="/message">Message</router-link></li>
56 56 <li><router-link to="/notice">Notice</router-link></li>
  57 + <li><router-link to="/avatar">Avatar</router-link></li>
  58 + <li><router-link to="/color-picker">ColorPicker</router-link></li>
57 59 </ul>
58 60 </nav>
59 61 <router-view></router-view>
... ...
examples/main.js
... ... @@ -180,6 +180,14 @@ const router = new VueRouter({
180 180 {
181 181 path: '/notice',
182 182 component: require('./routers/notice.vue')
  183 + },
  184 + {
  185 + path: '/avatar',
  186 + component: require('./routers/avatar.vue')
  187 + },
  188 + {
  189 + path: '/color-picker',
  190 + component: require('./routers/color-picker.vue')
183 191 }
184 192 ]
185 193 });
... ...
examples/routers/avatar.vue 0 โ†’ 100644
  1 +<template>
  2 + <div>
  3 + <Avatar icon="person" size="large" style="background-color: #fde3cf;color: #f56a00"></Avatar>
  4 + <Avatar icon="person"></Avatar>
  5 + <Avatar icon="person" size="small"></Avatar>
  6 + <Avatar icon="person" size="large" shape="square"></Avatar>
  7 + <Avatar icon="person" shape="square"></Avatar>
  8 + <Avatar icon="person" size="small" shape="square"></Avatar>
  9 + <br><br>
  10 + <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="large"></Avatar>
  11 + <Avatar src="https://avatars2.githubusercontent.com/u/5370542?v=4&s=460"></Avatar>
  12 + <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="small"></Avatar>
  13 + <Avatar src="https://avatars2.githubusercontent.com/u/5370542?v=4&s=460" size="large" shape="square"></Avatar>
  14 + <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" shape="square"></Avatar>
  15 + <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" size="small" shape="square"></Avatar>
  16 + <br><br>
  17 + <Avatar size="large">Leo</Avatar>
  18 + <Avatar size="large">A</Avatar>
  19 + <Avatar size="default">A</Avatar>
  20 + <Avatar size="small">A</Avatar>
  21 + <Avatar size="large">Tomserm</Avatar>
  22 + <Avatar size="large">{{ name }}</Avatar>
  23 + {{ name }}
  24 + <br><br>
  25 + <Badge dot>
  26 + <Avatar icon="person" shape="square"></Avatar>
  27 + </Badge>
  28 + <Badge :count="3">
  29 + <Avatar icon="person" shape="square"></Avatar>
  30 + </Badge>
  31 + <Button @click="change">change</Button>
  32 + </div>
  33 +</template>
  34 +<script>
  35 + export default {
  36 + data () {
  37 + return {
  38 + name: 'Aresn'
  39 + }
  40 + },
  41 + methods: {
  42 + change () {
  43 + this.name = 'Tomserm'
  44 + }
  45 + }
  46 + }
  47 +</script>
... ...
examples/routers/cascader.vue
1 1 <template>
2   - <div style="width: 400px;">
3   - <Row>
4   - <i-col span="12">
5   - <Cascader transfer v-model="value3" :data="data" filterable></Cascader>
6   - </i-col>
7   - <i-col span="12">
8   - <Cascader v-model="value3" :data="data" filterable></Cascader>
9   - </i-col>
10   - </Row>
11   - </div>
  2 + <Cascader :data="data4" :load-data="loadData"></Cascader>
12 3 </template>
13 4 <script>
14 5 export default {
15 6 data () {
16 7 return {
17   - data: [{
18   - value: 'beijing',
19   - label: 'ๅŒ—ไบฌ',
20   - children: [
21   - {
22   - value: 'gugong',
23   - label: 'ๆ•…ๅฎซ'
24   - },
25   - {
26   - value: 'tiantan',
27   - label: 'ๅคฉๅ›'
28   - },
29   - {
30   - value: 'wangfujing',
31   - label: '็Ž‹ๅบœไบ•'
32   - }
33   - ]
34   - }, {
35   - value: 'jiangsu',
36   - label: 'ๆฑŸ่‹',
37   - children: [
38   - {
39   - value: 'nanjing',
40   - label: 'ๅ—ไบฌ',
41   - children: [
42   - {
43   - value: 'fuzimiao',
44   - label: 'ๅคซๅญๅบ™',
45   - }
46   - ]
47   - },
48   - {
49   - value: 'suzhou',
50   - label: '่‹ๅทž',
51   - children: [
52   - {
53   - value: 'zhuozhengyuan',
54   - label: 'ๆ‹™ๆ”ฟๅ›ญ',
55   - },
56   - {
57   - value: 'shizilin',
58   - label: '็‹ฎๅญๆž—',
59   - }
60   - ]
61   - }
62   - ],
63   - }],
64   - value3: []
  8 + data4: [
  9 + {
  10 + value: 'beijing',
  11 + label: 'ๅŒ—ไบฌ',
  12 + children: [],
  13 + loading: false
  14 + },
  15 + {
  16 + value: 'hangzhou',
  17 + label: 'ๆญๅทž',
  18 + children: [],
  19 + loading:false
  20 + }
  21 + ]
  22 + }
  23 + },
  24 + methods: {
  25 + loadData (item, callback) {
  26 + item.loading = true;
  27 + setTimeout(() => {
  28 + console.log(1)
  29 + if (item.value === 'beijing') {
  30 + item.children = [
  31 +// {
  32 +// value: 'talkingdata',
  33 +// label: 'TalkingData'
  34 +// },
  35 +// {
  36 +// value: 'baidu',
  37 +// label: '็™พๅบฆ'
  38 +// },
  39 +// {
  40 +// value: 'sina',
  41 +// label: 'ๆ–ฐๆตช'
  42 +// }
  43 + ];
  44 + } else if (item.value === 'hangzhou') {
  45 + item.children = [
  46 + {
  47 + value: 'ali',
  48 + label: '้˜ฟ้‡Œๅทดๅทด'
  49 + },
  50 + {
  51 + value: '163',
  52 + label: '็ฝ‘ๆ˜“'
  53 + }
  54 + ];
  55 + }
  56 + item.loading = false;
  57 + callback();
  58 + }, 1000);
65 59 }
66 60 }
67 61 }
... ...
examples/routers/checkbox.vue
1 1 <template>
2 2 <div>
  3 + <div>
  4 + <Checkbox true-value="true" false-value="false" v-model="testValue1">test string</Checkbox>
  5 + {{ testValue1 }}
  6 + </div>
  7 + <div>
  8 + <Checkbox :true-value="0" :false-value="1" v-model="testValue2">test number</Checkbox>
  9 + {{ testValue2 }}
  10 + </div>
3 11 <Checkbox-group v-model="fruit">
4   - <Checkbox v-for="item in tags" :label="item.label" :key="item"></Checkbox>
  12 + <Checkbox v-for="item in tags" :label="item.label" :key="item.label" true-value="true"></Checkbox>
5 13 </Checkbox-group>
6 14 <div>{{ fruit }}</div>
7 15 </div>
... ... @@ -12,7 +20,9 @@
12 20 return {
13 21 social: ['facebook', 'github'],
14 22 fruit: ['่‹นๆžœ'],
15   - tags: []
  23 + tags: [],
  24 + testValue1: null,
  25 + testValue2: null
16 26 }
17 27 },
18 28 mounted () {
... ...
examples/routers/color-picker.vue 0 โ†’ 100644
  1 +<template>
  2 + <div style="margin: 100px;">
  3 + <!--<Input placeholder="่ฏท่พ“ๅ…ฅ..." size="large" style="width: 50px;"></Input>-->
  4 + <color-picker placement="bottom-start" size="large"></color-picker>
  5 + <!--<Date-picker type="date" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" size="large" style="width: 200px"></Date-picker>-->
  6 + <color-picker placement="bottom-start" size="default"></color-picker>
  7 + <!--<Date-picker type="date" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" style="width: 200px"></Date-picker>-->
  8 + <color-picker placement="bottom-start" size="small"></color-picker>
  9 + <!--<Date-picker type="date" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" size="small" style="width: 200px"></Date-picker>-->
  10 + </div>
  11 +</template>
  12 +<script>
  13 + export default {
  14 + props: {},
  15 + data () {
  16 + return {};
  17 + },
  18 + computed: {},
  19 + methods: {}
  20 + };
  21 +</script>
0 22 \ No newline at end of file
... ...
examples/routers/date.vue
... ... @@ -2,12 +2,16 @@
2 2 <div>
3 3 <Date-picker transfer type="daterange" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" style="width: 200px"></Date-picker>
4 4 <Date-picker type="daterange" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" style="width: 200px"></Date-picker>
5   - <Date-picker type="daterange" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" style="width: 200px"></Date-picker>
  5 + <Date-picker type="datetimerange" placeholder="้€‰ๆ‹ฉๆ—ฅๆœŸ" style="width: 200px" @on-change="changeDate"></Date-picker>
6 6 </div>
7 7 </template>
8 8 <script>
9 9 export default {
10   -
  10 + methods: {
  11 + changeDate(date){
  12 + console.log(date);
  13 + }
  14 + }
11 15 }
12 16 </script>
13 17  
... ...
examples/routers/form.vue
1 1 <template>
2 2 <Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
3   - <Form-item label="ๅง“ๅ" prop="name">
  3 + <Form-item prop="name">
  4 + <span slot="label"><Icon type="ionic"></Icon></span>
4 5 <Input v-model="formValidate.name" placeholder="่ฏท่พ“ๅ…ฅๅง“ๅ"></Input>
5 6 </Form-item>
6 7 <Form-item label="้‚ฎ็ฎฑ" prop="mail">
... ...
examples/routers/page.vue
1 1 <template>
2   - <Page :total="100" show-sizer show-elevator show-total></Page>
  2 + <div>
  3 + <Page :total="total" show-sizer show-elevator show-total :current.sync="current"></Page>
  4 + {{ current }}
  5 + <Button type="primary" @click="subject">- 1</Button>
  6 + <Button type="primary" @click="change">Change</Button>
  7 + </div>
3 8 </template>
4 9 <script>
5 10 export default {
6   -
  11 + data () {
  12 + return {
  13 + current: 1,
  14 + total: 21
  15 + }
  16 + },
  17 + methods: {
  18 + subject() {
  19 + this.total -= 1;
  20 + },
  21 + change() {
  22 + this.current = 1;
  23 + }
  24 + }
7 25 }
8 26 </script>
... ...
examples/routers/poptip.vue
1 1 <template>
2   - <div>
3   - <Poptip trigger="hover" title="ๆ็คบๆ ‡้ข˜" content="ๆ็คบๅ†…ๅฎน">
4   - <Button>hover ๆฟ€ๆดป</Button>
5   - </Poptip>
6   - <Poptip transfer title="ๆ็คบๆ ‡้ข˜" content="ๆ็คบๅ†…ๅฎน">
7   - <Button>click ๆฟ€ๆดป</Button>
8   - </Poptip>
9   - <Poptip trigger="focus" title="ๆ็คบๆ ‡้ข˜" content="ๆ็คบๅ†…ๅฎน">
10   - <Button>focus ๆฟ€ๆดป</Button>
11   - </Poptip>
12   - <Poptip trigger="focus" title="ๆ็คบๆ ‡้ข˜" content="ๆ็คบๅ†…ๅฎน">
13   - <i-input placeholder="่พ“ๅ…ฅๆก†็š„ focus"></i-input>
  2 + <div style="margin: 100px;">
  3 + <Poptip
  4 + confirm
  5 + transfer
  6 + title="ๆ‚จ็กฎ่ฎคๅˆ ้™ค่ฟ™ๆกๅ†…ๅฎนๅ—๏ผŸ"
  7 + @on-ok="ok"
  8 + @on-cancel="cancel">
  9 + <Button>ๅˆ ้™ค</Button>
14 10 </Poptip>
15 11 </div>
16 12 </template>
17 13 <script>
18 14 export default {
19   -
  15 + methods: {
  16 + ok () {
  17 + this.$Message.info('็‚นๅ‡ปไบ†็กฎๅฎš');
  18 + },
  19 + cancel () {
  20 + this.$Message.info('็‚นๅ‡ปไบ†ๅ–ๆถˆ');
  21 + }
  22 + }
20 23 }
21 24 </script>
... ...
examples/routers/radio.vue
1 1 <template>
2 2 <div>
  3 + <Radio true-value="true" false-value="false" v-model="testValue">test</Radio> {{ testValue }}
3 4 <Radio-group v-model="date.sex">
4 5 <div v-if="show">
5   - <Radio label="male"></Radio>
6   - <Radio label="female"></Radio>
  6 + <Radio label="male" true-value="true" false-value="false"></Radio>
  7 + <Radio label="female" true-value="true" false-value="false"></Radio>
7 8 </div>
8 9 </Radio-group>
  10 + {{ date }}
9 11 <Button @click="handleChange">change</Button>
10 12 </div>
11 13 </template>
... ... @@ -16,7 +18,8 @@
16 18 date: {
17 19 sex: 'male'
18 20 },
19   - show: false
  21 + show: false,
  22 + testValue: null
20 23 }
21 24 },
22 25 methods: {
... ...
examples/routers/tree.vue
... ... @@ -29,7 +29,8 @@
29 29 },
30 30 {
31 31 title: 'child2',
32   - id: '1-2'
  32 + id: '1-2',
  33 + children: []
33 34 }
34 35 ]
35 36 }
... ...
package.json
1 1 {
2 2 "name": "iview",
3   - "version": "2.0.0",
  3 + "version": "2.1.0",
4 4 "title": "iView",
5 5 "description": "A high quality UI components Library with Vue.js",
6 6 "homepage": "http://www.iviewui.com",
... ...
src/components/avatar/avatar.vue 0 โ†’ 100644
  1 +<template>
  2 + <span :class="classes">
  3 + <img :src="src" v-if="src">
  4 + <Icon :type="icon" v-else-if="icon"></Icon>
  5 + <span ref="children" :class="[prefixCls + '-string']" :style="childrenStyle" v-else><slot></slot></span>
  6 + </span>
  7 +</template>
  8 +<script>
  9 + import Icon from '../icon';
  10 + import { oneOf } from '../../utils/assist';
  11 +
  12 + const prefixCls = 'ivu-avatar';
  13 +
  14 + export default {
  15 + name: 'Avatar',
  16 + components: { Icon },
  17 + props: {
  18 + shape: {
  19 + validator (value) {
  20 + return oneOf(value, ['circle', 'square']);
  21 + },
  22 + default: 'circle'
  23 + },
  24 + size: {
  25 + validator (value) {
  26 + return oneOf(value, ['small', 'large', 'default']);
  27 + },
  28 + default: 'default'
  29 + },
  30 + src: {
  31 + type: String
  32 + },
  33 + icon: {
  34 + type: String
  35 + }
  36 + },
  37 + data () {
  38 + return {
  39 + prefixCls: prefixCls,
  40 + scale: 1,
  41 + isSlotShow: false
  42 + };
  43 + },
  44 + computed: {
  45 + classes () {
  46 + return [
  47 + `${prefixCls}`,
  48 + `${prefixCls}-${this.shape}`,
  49 + `${prefixCls}-${this.size}`,
  50 + {
  51 + [`${prefixCls}-image`]: !!this.src,
  52 + [`${prefixCls}-icon`]: !!this.icon
  53 + }
  54 + ];
  55 + },
  56 + childrenStyle () {
  57 + let style = {};
  58 + if (this.isSlotShow) {
  59 + style = {
  60 + msTransform: `scale(${this.scale})`,
  61 + WebkitTransform: `scale(${this.scale})`,
  62 + transform: `scale(${this.scale})`,
  63 + position: 'absolute',
  64 + display: 'inline-block',
  65 + left: `calc(50% - ${Math.round(this.$refs.children.offsetWidth / 2)}px)`
  66 + };
  67 + }
  68 + return style;
  69 + }
  70 + },
  71 + methods: {
  72 + setScale () {
  73 + this.isSlotShow = !this.src && !this.icon;
  74 + if (this.$slots.default) {
  75 + const childrenWidth = this.$refs.children.offsetWidth;
  76 + const avatarWidth = this.$el.getBoundingClientRect().width;
  77 + // add 4px gap for each side to get better performance
  78 + if (avatarWidth - 8 < childrenWidth) {
  79 + this.scale = (avatarWidth - 8) / childrenWidth;
  80 + } else {
  81 + this.scale = 1;
  82 + }
  83 + }
  84 + }
  85 + },
  86 + mounted () {
  87 + this.setScale();
  88 + },
  89 + updated () {
  90 + this.setScale();
  91 + }
  92 + };
  93 +</script>
0 94 \ No newline at end of file
... ...
src/components/avatar/index.js 0 โ†’ 100644
  1 +import Avatar from './avatar.vue';
  2 +export default Avatar;
0 3 \ No newline at end of file
... ...
src/components/cascader/caspanel.vue
... ... @@ -15,7 +15,7 @@
15 15 <script>
16 16 import Casitem from './casitem.vue';
17 17 import Emitter from '../../mixins/emitter';
18   - import { findComponentUpward } from '../../utils/assist';
  18 + import { findComponentUpward, findComponentDownward } from '../../utils/assist';
19 19  
20 20 let key = 1;
21 21  
... ... @@ -67,7 +67,9 @@
67 67 if (fromUser) {
68 68 cascader.isLoadedChildren = true;
69 69 }
70   - this.handleTriggerItem(item);
  70 + if (item.children.length) {
  71 + this.handleTriggerItem(item);
  72 + }
71 73 });
72 74 return;
73 75 }
... ... @@ -84,6 +86,14 @@
84 86 changeOnSelect: this.changeOnSelect,
85 87 fromInit: fromInit
86 88 });
  89 +
  90 + // #1553
  91 + if (this.changeOnSelect) {
  92 + const Caspanel = findComponentDownward(this, 'Caspanel');
  93 + if (Caspanel) {
  94 + Caspanel.$emit('on-clear', true);
  95 + }
  96 + }
87 97 } else {
88 98 this.sublist = [];
89 99 this.dispatch('Cascader', 'on-result-change', {
... ... @@ -135,9 +145,16 @@
135 145 }
136 146 }
137 147 });
138   - this.$on('on-clear', () => {
  148 + // deep for #1553
  149 + this.$on('on-clear', (deep = false) => {
139 150 this.sublist = [];
140 151 this.tmpItem = {};
  152 + if (deep) {
  153 + const Caspanel = findComponentDownward(this, 'Caspanel');
  154 + if (Caspanel) {
  155 + Caspanel.$emit('on-clear', true);
  156 + }
  157 + }
141 158 });
142 159 }
143 160 };
... ...
src/components/checkbox/checkbox.vue
... ... @@ -36,7 +36,15 @@
36 36 default: false
37 37 },
38 38 value: {
39   - type: Boolean,
  39 + type: [String, Number, Boolean],
  40 + default: false
  41 + },
  42 + trueValue: {
  43 + type: [String, Number, Boolean],
  44 + default: true
  45 + },
  46 + falseValue: {
  47 + type: [String, Number, Boolean],
40 48 default: false
41 49 },
42 50 label: {
... ... @@ -102,21 +110,26 @@
102 110  
103 111 const checked = event.target.checked;
104 112 this.currentValue = checked;
105   - this.$emit('input', checked);
  113 +
  114 + let value = checked ? this.trueValue : this.falseValue;
  115 + this.$emit('input', value);
106 116  
107 117 if (this.group) {
108 118 this.parent.change(this.model);
109 119 } else {
110   - this.$emit('on-change', checked);
111   - this.dispatch('FormItem', 'on-form-change', checked);
  120 + this.$emit('on-change', value);
  121 + this.dispatch('FormItem', 'on-form-change', value);
112 122 }
113 123 },
114 124 updateModel () {
115   - this.currentValue = this.value;
  125 + this.currentValue = this.value === this.trueValue;
116 126 }
117 127 },
118 128 watch: {
119   - value () {
  129 + value (val) {
  130 + if (val !== this.trueValue && val !== this.falseValue) {
  131 + throw 'Value should be trueValue or falseValue.';
  132 + }
120 133 this.updateModel();
121 134 }
122 135 }
... ...
src/components/color-picker/color-picker.vue 0 โ†’ 100644
  1 +<template>
  2 + <Dropdown trigger="click" :transfer="transfer" :placement="placement">
  3 + <div :class="wrapClasses">
  4 + <i class="ivu-icon ivu-icon-arrow-down-b ivu-input-icon ivu-input-icon-normal"></i>
  5 + <div :class="inputClasses">
  6 + <div :class="[prefixCls + '-color']" style="background-color: rgb(32, 160, 255);"></div>
  7 + </div>
  8 + </div>
  9 + <Dropdown-menu slot="list">
  10 + <p>ๅธธ็”จไบŽๅ„็ง่‡ชๅฎšไน‰ไธ‹ๆ‹‰ๅ†…ๅฎน็š„ๅœบๆ™ฏใ€‚</p>
  11 + <div style="text-align: right;margin:10px;">
  12 + <Button type="primary">ๅ…ณ้—ญ</Button>
  13 + </div>
  14 + </Dropdown-menu>
  15 + </Dropdown>
  16 +</template>
  17 +<script>
  18 + import Dropdown from '../dropdown/dropdown.vue';
  19 + import DropdownMenu from '../dropdown/dropdown-menu.vue';
  20 + import { oneOf } from '../../utils/assist';
  21 +
  22 + const prefixCls = 'ivu-color-picker';
  23 + const inputPrefixCls = 'ivu-input';
  24 +
  25 + export default {
  26 + name: 'ColorPicker',
  27 + components: { Dropdown, DropdownMenu },
  28 + props: {
  29 + value: {
  30 + type: String
  31 + },
  32 + alpha: {
  33 + type: Boolean,
  34 + default: false
  35 + },
  36 + format: {
  37 + validator (value) {
  38 + return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
  39 + }
  40 + },
  41 + disabled: {
  42 + type: Boolean,
  43 + default: false
  44 + },
  45 + size: {
  46 + validator (value) {
  47 + return oneOf(value, ['small', 'large', 'default']);
  48 + }
  49 + },
  50 + placement: {
  51 + validator (value) {
  52 + return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
  53 + },
  54 + default: 'bottom'
  55 + },
  56 + transfer: {
  57 + type: Boolean,
  58 + default: false
  59 + }
  60 + },
  61 + data () {
  62 + return {
  63 + prefixCls: prefixCls,
  64 + currentValue: this.value
  65 + };
  66 + },
  67 + computed: {
  68 + wrapClasses () {
  69 + return [
  70 + `${prefixCls}-rel`,
  71 + `${inputPrefixCls}-wrapper`,
  72 + `${inputPrefixCls}-wrapper-${this.size}`
  73 + ];
  74 + },
  75 + inputClasses () {
  76 + return [
  77 + `${prefixCls}-input`,
  78 + `${inputPrefixCls}`,
  79 + `${inputPrefixCls}-${this.size}`,
  80 + {
  81 + [`${inputPrefixCls}-disabled`]: this.disabled
  82 + }
  83 + ];
  84 + }
  85 + },
  86 + methods: {
  87 +
  88 + }
  89 + };
  90 +</script>
0 91 \ No newline at end of file
... ...
src/components/color-picker/color.js 0 โ†’ 100644
src/components/color-picker/index.js 0 โ†’ 100644
  1 +import ColorPicker from './color-picker.vue';
  2 +export default ColorPicker;
0 3 \ No newline at end of file
... ...
src/components/date-picker/base/time-spinner.vue
1 1 <template>
2 2 <div :class="classes">
3 3 <div :class="[prefixCls+ '-list']" ref="hours">
4   - <ul :class="[prefixCls + '-ul']" @click="handleClickHours">
5   - <li :class="getCellCls(item)" v-for="(item, index) in hoursList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
  4 + <ul :class="[prefixCls + '-ul']">
  5 + <li :class="getCellCls(item)" v-for="item in hoursList" v-show="!item.hide" @click="handleClick('hours', item)">{{ formatTime(item.text) }}</li>
6 6 </ul>
7 7 </div>
8 8 <div :class="[prefixCls+ '-list']" ref="minutes">
9   - <ul :class="[prefixCls + '-ul']" @click="handleClickMinutes">
10   - <li :class="getCellCls(item)" v-for="(item, index) in minutesList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
  9 + <ul :class="[prefixCls + '-ul']">
  10 + <li :class="getCellCls(item)" v-for="item in minutesList" v-show="!item.hide" @click="handleClick('minutes', item)">{{ formatTime(item.text) }}</li>
11 11 </ul>
12 12 </div>
13 13 <div :class="[prefixCls+ '-list']" v-show="showSeconds" ref="seconds">
14   - <ul :class="[prefixCls + '-ul']" @click="handleClickSeconds">
15   - <li :class="getCellCls(item)" v-for="(item, index) in secondsList" v-show="!item.hide" :index="index">{{ formatTime(item.text) }}</li>
  14 + <ul :class="[prefixCls + '-ul']">
  15 + <li :class="getCellCls(item)" v-for="item in secondsList" v-show="!item.hide" @click="handleClick('seconds', item)">{{ formatTime(item.text) }}</li>
16 16 </ul>
17 17 </div>
18 18 </div>
... ... @@ -41,10 +41,15 @@
41 41 showSeconds: {
42 42 type: Boolean,
43 43 default: true
  44 + },
  45 + steps: {
  46 + type: Array,
  47 + default: () => []
44 48 }
45 49 },
46 50 data () {
47 51 return {
  52 + spinerSteps: [1, 1, 1].map((one, i) => Math.abs(this.steps[i]) || one),
48 53 prefixCls: prefixCls,
49 54 compiled: false
50 55 };
... ... @@ -60,6 +65,7 @@
60 65 },
61 66 hoursList () {
62 67 let hours = [];
  68 + const step = this.spinerSteps[0];
63 69 const hour_tmpl = {
64 70 text: 0,
65 71 selected: false,
... ... @@ -67,7 +73,7 @@
67 73 hide: false
68 74 };
69 75  
70   - for (let i = 0; i < 24; i++) {
  76 + for (let i = 0; i < 24; i += step) {
71 77 const hour = deepCopy(hour_tmpl);
72 78 hour.text = i;
73 79  
... ... @@ -83,6 +89,7 @@
83 89 },
84 90 minutesList () {
85 91 let minutes = [];
  92 + const step = this.spinerSteps[1];
86 93 const minute_tmpl = {
87 94 text: 0,
88 95 selected: false,
... ... @@ -90,7 +97,7 @@
90 97 hide: false
91 98 };
92 99  
93   - for (let i = 0; i < 60; i++) {
  100 + for (let i = 0; i < 60; i += step) {
94 101 const minute = deepCopy(minute_tmpl);
95 102 minute.text = i;
96 103  
... ... @@ -101,11 +108,11 @@
101 108 if (this.minutes === i) minute.selected = true;
102 109 minutes.push(minute);
103 110 }
104   -
105 111 return minutes;
106 112 },
107 113 secondsList () {
108 114 let seconds = [];
  115 + const step = this.spinerSteps[2];
109 116 const second_tmpl = {
110 117 text: 0,
111 118 selected: false,
... ... @@ -113,7 +120,7 @@
113 120 hide: false
114 121 };
115 122  
116   - for (let i = 0; i < 60; i++) {
  123 + for (let i = 0; i < 60; i += step) {
117 124 const second = deepCopy(second_tmpl);
118 125 second.text = i;
119 126  
... ... @@ -138,24 +145,11 @@
138 145 }
139 146 ];
140 147 },
141   - handleClickHours (event) {
142   - this.handleClick('hours', event);
143   - },
144   - handleClickMinutes (event) {
145   - this.handleClick('minutes', event);
146   - },
147   - handleClickSeconds (event) {
148   - this.handleClick('seconds', event);
149   - },
150   - handleClick (type, event) {
151   - const target = event.target;
152   - if (target.tagName === 'LI') {
153   - const cell = this[`${type}List`][parseInt(event.target.getAttribute('index'))];
154   - if (cell.disabled) return;
155   - const data = {};
156   - data[type] = cell.text;
157   - this.$emit('on-change', data);
158   - }
  148 + handleClick (type, cell) {
  149 + if (cell.disabled) return;
  150 + const data = {};
  151 + data[type] = cell.text;
  152 + this.$emit('on-change', data);
159 153 this.$emit('on-pick-click');
160 154 },
161 155 scroll (type, index) {
... ... @@ -183,20 +177,24 @@
183 177 },
184 178 formatTime (text) {
185 179 return text < 10 ? '0' + text : text;
  180 + },
  181 + getItemIndex(type, val){
  182 + const item = this[`${type}List`].find(obj => obj.text == val);
  183 + return this[`${type}List`].indexOf(item);
186 184 }
187 185 },
188 186 watch: {
189 187 hours (val) {
190 188 if (!this.compiled) return;
191   - this.scroll('hours', val);
  189 + this.scroll('hours', this.getItemIndex('hours', val));
192 190 },
193 191 minutes (val) {
194 192 if (!this.compiled) return;
195   - this.scroll('minutes', val);
  193 + this.scroll('minutes', this.getItemIndex('minutes', val));
196 194 },
197 195 seconds (val) {
198 196 if (!this.compiled) return;
199   - this.scroll('seconds', val);
  197 + this.scroll('seconds', this.getItemIndex('seconds', val));
200 198 }
201 199 },
202 200 mounted () {
... ... @@ -204,4 +202,4 @@
204 202 this.$nextTick(() => this.compiled = true);
205 203 }
206 204 };
207   -</script>
208 205 \ No newline at end of file
  206 +</script>
... ...
src/components/date-picker/panel/time.vue
... ... @@ -6,6 +6,7 @@
6 6 <time-spinner
7 7 ref="timeSpinner"
8 8 :show-seconds="showSeconds"
  9 + :steps="steps"
9 10 :hours="hours"
10 11 :minutes="minutes"
11 12 :seconds="seconds"
... ... @@ -39,6 +40,12 @@
39 40 name: 'TimePicker',
40 41 mixins: [ Mixin, Locale ],
41 42 components: { TimeSpinner, Confirm },
  43 + props: {
  44 + steps: {
  45 + type: Array,
  46 + default: () => []
  47 + }
  48 + },
42 49 data () {
43 50 return {
44 51 prefixCls: prefixCls,
... ... @@ -113,4 +120,4 @@
113 120 if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
114 121 }
115 122 };
116   -</script>
117 123 \ No newline at end of file
  124 +</script>
... ...
src/components/date-picker/picker.vue
... ... @@ -32,7 +32,6 @@
32 32 </div>
33 33 </template>
34 34 <script>
35   - import Vue from 'vue';
36 35 import iInput from '../../components/input/input.vue';
37 36 import Drop from '../../components/select/dropdown.vue';
38 37 import clickoutside from '../../directives/clickoutside';
... ... @@ -397,7 +396,7 @@
397 396 let isConfirm = this.confirm;
398 397 const type = this.type;
399 398  
400   - this.picker = new Vue(this.panel).$mount(this.$refs.picker);
  399 + this.picker = this.Panel.$mount(this.$refs.picker);
401 400 if (type === 'datetime' || type === 'datetimerange') {
402 401 isConfirm = true;
403 402 this.picker.showTime = true;
... ... @@ -459,7 +458,7 @@
459 458 ).formatter;
460 459  
461 460 let newDate = formatter(date, format);
462   - if (type === 'daterange' || type === 'timerange') {
  461 + if (type === 'daterange' || type === 'timerange' || type === 'datetimerange') {
463 462 newDate = [newDate.split(RANGE_SEPARATOR)[0], newDate.split(RANGE_SEPARATOR)[1]];
464 463 }
465 464 return newDate;
... ...
src/components/date-picker/picker/date-picker.js
  1 +import Vue from 'vue';
1 2 import Picker from '../picker.vue';
2 3 import DatePanel from '../panel/date.vue';
3 4 import DateRangePanel from '../panel/date-range.vue';
... ... @@ -31,6 +32,7 @@ export default {
31 32 }
32 33 }
33 34  
34   - this.panel = getPanel(this.type);
  35 + const panel = getPanel(this.type);
  36 + this.Panel = new Vue(panel);
35 37 }
36 38 };
... ...
src/components/date-picker/picker/time-picker.js
  1 +import Vue from 'vue';
1 2 import Picker from '../picker.vue';
2 3 import TimePanel from '../panel/time.vue';
3 4 import TimeRangePanel from '../panel/time-range.vue';
... ... @@ -21,6 +22,10 @@ export default {
21 22 },
22 23 default: 'time'
23 24 },
  25 + steps: {
  26 + type: Array,
  27 + default: () => []
  28 + },
24 29 value: {}
25 30 },
26 31 created () {
... ... @@ -31,6 +36,11 @@ export default {
31 36 this.currentValue = '';
32 37 }
33 38 }
34   - this.panel = getPanel(this.type);
  39 + const Panel = Vue.extend(getPanel(this.type));
  40 + this.Panel = new Panel({
  41 + propsData: {
  42 + steps: this.steps
  43 + }
  44 + });
35 45 }
36   -};
37 46 \ No newline at end of file
  47 +};
... ...
src/components/form/form-item.vue
1 1 <template>
2 2 <div :class="classes">
3   - <label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label"><slot name="label">{{ label }}</slot></label>
  3 + <label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label || $slots.label"><slot name="label">{{ label }}</slot></label>
4 4 <div :class="[prefixCls + '-content']" :style="contentStyles">
5 5 <slot></slot>
6 6 <transition name="fade">
... ... @@ -177,6 +177,7 @@
177 177  
178 178 callback(this.validateMessage);
179 179 });
  180 + this.validateDisabled = false;
180 181 },
181 182 resetField () {
182 183 this.validateState = '';
... ...
src/components/input/input.vue
... ... @@ -74,7 +74,7 @@
74 74 },
75 75 size: {
76 76 validator (value) {
77   - return oneOf(value, ['small', 'large']);
  77 + return oneOf(value, ['small', 'large', 'default']);
78 78 }
79 79 },
80 80 placeholder: {
... ...
src/components/page/page.vue
... ... @@ -135,6 +135,12 @@
135 135 };
136 136 },
137 137 watch: {
  138 + total (val) {
  139 + let maxPage = Math.ceil(val / this.currentPageSize);
  140 + if (maxPage < this.currentPage && maxPage > 0) {
  141 + this.currentPage = maxPage;
  142 + }
  143 + },
138 144 current (val) {
139 145 this.currentPage = val;
140 146 },
... ... @@ -208,6 +214,7 @@
208 214 changePage (page) {
209 215 if (this.currentPage != page) {
210 216 this.currentPage = page;
  217 + this.$emit('update:current', page);
211 218 this.$emit('on-change', page);
212 219 }
213 220 },
... ...
src/components/radio/radio.vue
... ... @@ -22,7 +22,15 @@
22 22 mixins: [ Emitter ],
23 23 props: {
24 24 value: {
25   - type: Boolean,
  25 + type: [String, Number, Boolean],
  26 + default: false
  27 + },
  28 + trueValue: {
  29 + type: [String, Number, Boolean],
  30 + default: true
  31 + },
  32 + falseValue: {
  33 + type: [String, Number, Boolean],
26 34 default: false
27 35 },
28 36 label: {
... ... @@ -83,7 +91,9 @@
83 91  
84 92 const checked = event.target.checked;
85 93 this.currentValue = checked;
86   - this.$emit('input', checked);
  94 +
  95 + let value = checked ? this.trueValue : this.falseValue;
  96 + this.$emit('input', value);
87 97  
88 98 if (this.group && this.label !== undefined) {
89 99 this.parent.change({
... ... @@ -92,16 +102,19 @@
92 102 });
93 103 }
94 104 if (!this.group) {
95   - this.$emit('on-change', checked);
96   - this.dispatch('FormItem', 'on-form-change', checked);
  105 + this.$emit('on-change', value);
  106 + this.dispatch('FormItem', 'on-form-change', value);
97 107 }
98 108 },
99 109 updateValue () {
100   - this.currentValue = this.value;
  110 + this.currentValue = this.value === this.trueValue;
101 111 }
102 112 },
103 113 watch: {
104   - value () {
  114 + value (val) {
  115 + if (val !== this.trueValue && val !== this.falseValue) {
  116 + throw 'Value should be trueValue or falseValue.';
  117 + }
105 118 this.updateValue();
106 119 }
107 120 }
... ...
src/components/table/export-csv.js
... ... @@ -41,7 +41,7 @@ const csv = {
41 41 _getDownloadUrl (text) {
42 42 const BOM = '\uFEFF';
43 43 // Add BOM to text for open in excel correctly
44   - if (window.Blob && window.URL && window.URL.createObjectURL && !has('Safari')) {
  44 + if (window.Blob && window.URL && window.URL.createObjectURL) {
45 45 const csvData = new Blob([BOM + text], { type: 'text/csv' });
46 46 return URL.createObjectURL(csvData);
47 47 } else {
... ... @@ -66,7 +66,6 @@ const csv = {
66 66 const link = document.createElement('a');
67 67 link.download = filename;
68 68 link.href = this._getDownloadUrl(text);
69   - link.target = '_blank';
70 69 document.body.appendChild(link);
71 70 link.click();
72 71 document.body.removeChild(link);
... ...
src/components/tree/tree.vue
... ... @@ -71,7 +71,7 @@
71 71 // init checked status
72 72 function reverseChecked(data) {
73 73 if (!data.nodeKey) data.nodeKey = key++;
74   - if (data.children) {
  74 + if (data.children && data.children.length) {
75 75 let checkedLength = 0;
76 76 data.children.forEach(node => {
77 77 if (node.children) node = reverseChecked(node);
... ...
src/index.js
... ... @@ -3,6 +3,7 @@ import &#39;core-js/fn/array/find-index&#39;;
3 3  
4 4 import Affix from './components/affix';
5 5 import Alert from './components/alert';
  6 +import Avatar from './components/avatar';
6 7 import BackTop from './components/back-top';
7 8 import Badge from './components/badge';
8 9 import Breadcrumb from './components/breadcrumb';
... ... @@ -13,6 +14,7 @@ import Cascader from &#39;./components/cascader&#39;;
13 14 import Checkbox from './components/checkbox';
14 15 import Circle from './components/circle';
15 16 import Collapse from './components/collapse';
  17 +import ColorPicker from './components/color-picker';
16 18 import DatePicker from './components/date-picker';
17 19 import Dropdown from './components/dropdown';
18 20 import Form from './components/form';
... ... @@ -49,6 +51,7 @@ import locale from &#39;./locale&#39;;
49 51 const iview = {
50 52 Affix,
51 53 Alert,
  54 + Avatar,
52 55 BackTop,
53 56 Badge,
54 57 Breadcrumb,
... ... @@ -63,6 +66,10 @@ const iview = {
63 66 Checkbox,
64 67 CheckboxGroup: Checkbox.Group,
65 68 iCircle: Circle,
  69 + Col,
  70 + iCol: Col,
  71 + Collapse,
  72 + ColorPicker,
66 73 DatePicker,
67 74 Dropdown,
68 75 DropdownItem: Dropdown.Item,
... ... @@ -70,9 +77,6 @@ const iview = {
70 77 Form,
71 78 iForm: Form,
72 79 FormItem: Form.Item,
73   - Col,
74   - iCol: Col,
75   - Collapse,
76 80 Icon,
77 81 Input,
78 82 iInput: Input,
... ...
src/locale/lang/pt-PT.js 0 โ†’ 100644
  1 +export default {
  2 + i: {
  3 + select: {
  4 + placeholder: 'Selecionar',
  5 + noMatch: 'Nรฃo encontrado',
  6 + loading: 'A carregar'
  7 + },
  8 + table: {
  9 + noDataText: 'Sem dados',
  10 + noFilteredDataText: 'Sem dados filtrados',
  11 + confirmFilter: 'Confirmar',
  12 + resetFilter: 'Limpar',
  13 + clearFilter: 'Todos'
  14 + },
  15 + datepicker: {
  16 + selectDate: 'Selecione a data',
  17 + selectTime: 'Selecione a hora',
  18 + startTime: 'Hora inicial',
  19 + endTime: 'Hora final',
  20 + clear: 'Limpar',
  21 + ok: 'Confirmar',
  22 + month: 'Mรชs',
  23 + month1: 'Janeiro',
  24 + month2: 'Fevereiro',
  25 + month3: 'Marรงo',
  26 + month4: 'Abril',
  27 + month5: 'Maio',
  28 + month6: 'Junho',
  29 + month7: 'Julho',
  30 + month8: 'Agosto',
  31 + month9: 'Setembro',
  32 + month10: 'Outubro',
  33 + month11: 'Novembro',
  34 + month12: 'Dezembro',
  35 + year: 'Ano',
  36 + weeks: {
  37 + sun: 'Dom',
  38 + mon: 'Seg',
  39 + tue: 'Ter',
  40 + wed: 'Qua',
  41 + thu: 'Qui',
  42 + fri: 'Sex',
  43 + sat: 'Sรกb'
  44 + },
  45 + months: {
  46 + m1: 'Jan',
  47 + m2: 'Fev',
  48 + m3: 'Mar',
  49 + m4: 'Abr',
  50 + m5: 'Mai',
  51 + m6: 'Jun',
  52 + m7: 'Jul',
  53 + m8: 'Ago',
  54 + m9: 'Set',
  55 + m10: 'Out',
  56 + m11: 'Nov',
  57 + m12: 'Dez'
  58 + }
  59 + },
  60 + transfer: {
  61 + titles: {
  62 + source: 'Origem',
  63 + target: 'Destino'
  64 + },
  65 + filterPlaceholder: 'Pesquise aqui',
  66 + notFoundText: 'Nรฃo encontrado'
  67 + },
  68 + modal: {
  69 + okText: 'Confirmar',
  70 + cancelText: 'Cancelar'
  71 + },
  72 + poptip: {
  73 + okText: 'Confirmar',
  74 + cancelText: 'Cancelar'
  75 + },
  76 + page: {
  77 + prev: 'Pรกgina anterior',
  78 + next: 'Prรณxima pรกgina',
  79 + total: 'Total',
  80 + item: 'item',
  81 + items: 'itens',
  82 + prev5: 'Voltar 5 pรกginas',
  83 + next5: 'Avanรงar 5 pรกginas',
  84 + page: '/page',
  85 + goto: 'Ir para',
  86 + p: ''
  87 + },
  88 + rate: {
  89 + star: 'Estrela',
  90 + stars: 'Estrelas'
  91 + },
  92 + tree: {
  93 + emptyText: 'Sem dados'
  94 + }
  95 + }
  96 +};
... ...
src/locale/lang/sv-SE.js 0 โ†’ 100644
  1 +export default {
  2 + i: {
  3 + select: {
  4 + placeholder: 'Vรคlj',
  5 + noMatch: 'Ingen trรคff',
  6 + loading: 'Ladar'
  7 + },
  8 + table: {
  9 + noDataText: 'Ingen data',
  10 + noFilteredDataText: 'Ingen filter data',
  11 + confirmFilter: 'Bekrรคfta',
  12 + resetFilter: 'ร…terstรคll filter',
  13 + clearFilter: 'Rensa filter'
  14 + },
  15 + datepicker: {
  16 + selectDate: 'Vรคlj datum',
  17 + selectTime: 'Vรคlj tidpunkt',
  18 + startTime: 'Start tid',
  19 + endTime: 'Slut tid',
  20 + clear: 'Rensa',
  21 + ok: 'Ok',
  22 + month: 'Mรฅnad',
  23 + month1: 'Januari',
  24 + month2: 'Februari',
  25 + month3: 'Mars',
  26 + month4: 'April',
  27 + month5: 'Maj',
  28 + month6: 'Juni',
  29 + month7: 'Juli',
  30 + month8: 'Augusti',
  31 + month9: 'September',
  32 + month10: 'Oktober',
  33 + month11: 'November',
  34 + month12: 'December',
  35 + year: 'ร…r',
  36 + weeks: {
  37 + sun: 'Sรถn',
  38 + mon: 'Mรฅn',
  39 + tue: 'Tis',
  40 + wed: 'Ons',
  41 + thu: 'Tor',
  42 + fri: 'Fre',
  43 + sat: 'Lรถr'
  44 + },
  45 + months: {
  46 + m1: 'Jan',
  47 + m2: 'Feb',
  48 + m3: 'Mar',
  49 + m4: 'Apr',
  50 + m5: 'Maj',
  51 + m6: 'Jun',
  52 + m7: 'Jul',
  53 + m8: 'Aug',
  54 + m9: 'Sep',
  55 + m10: 'Okt',
  56 + m11: 'Nov',
  57 + m12: 'Dec'
  58 + }
  59 + },
  60 + transfer: {
  61 + titles: {
  62 + source: 'Kรคlla',
  63 + target: 'Mรฅl'
  64 + },
  65 + filterPlaceholder: 'Sรถk hรคr',
  66 + notFoundText: 'Hittade inte'
  67 + },
  68 + modal: {
  69 + okText: 'Ok',
  70 + cancelText: 'Avbryt'
  71 + },
  72 + poptip: {
  73 + okText: 'Ok',
  74 + cancelText: 'Avbryt'
  75 + },
  76 + page: {
  77 + prev: 'Fรถregรฅende sida',
  78 + next: 'Nรคsta sida',
  79 + total: 'Totalt',
  80 + item: 'objekt',
  81 + items: 'objekt',
  82 + prev5: 'Fรถregรฅende 5 sidor',
  83 + next5: 'Nรคsta 5 sidor',
  84 + page: '/page',
  85 + goto: 'Gรฅ till',
  86 + p: ''
  87 + },
  88 + rate: {
  89 + star: 'Stjรคrna',
  90 + stars: 'Stjรคrnor'
  91 + },
  92 + tree: {
  93 + emptyText: 'Ingen data'
  94 + }
  95 + }
  96 +};
... ...
src/locale/lang/vi-VN.js
1 1 export default {
2   - i: {
3   - select: {
4   - placeholder: 'Chแปn',
5   - noMatch: 'Khรดng tรฌm thแบฅy',
6   - loading: 'ฤang tแบฃi'
7   - },
8   - table: {
9   - noDataText: 'Khรดng cรณ dแปฏ liแป‡u',
10   - noFilteredDataText: 'Khรดng cรณ dแปฏ liแป‡u lแปc',
11   - confirmFilter: 'Xรกc nhแบญn',
12   - resetFilter: 'Lร m lแบกi',
13   - clearFilter: 'Xรณa hแบฟt'
14   - },
15   - datepicker: {
16   - selectDate: 'Chแปn ngร y',
17   - selectTime: 'Chแปn giแป',
18   - startTime: 'Ngร y bแบฏt ฤ‘แบงu',
19   - endTime: 'Ngร y kแบฟt thรบc',
20   - clear: 'Xรณa',
21   - ok: 'ฤแป“ng รฝ',
22   - month: '',
23   - month1: 'Thรกng 1',
24   - month2: 'Thรกng 2',
25   - month3: 'Thรกng 3',
26   - month4: 'Thรกng 4',
27   - month5: 'Thรกng 5',
28   - month6: 'Thรกng 6',
29   - month7: 'Thรกng 7',
30   - month8: 'Thรกng 8',
31   - month9: 'Thรกng 9',
32   - month10: 'Thรกng 10',
33   - month11: 'Thรกng 11',
34   - month12: 'Thรกng 12',
35   - year: '',
36   - weeks: {
37   - sun: 'CN',
38   - mon: 'T2',
39   - tue: 'T3',
40   - wed: 'T4',
41   - thu: 'T5',
42   - fri: 'T6',
43   - sat: 'T7'
44   - },
45   - months: {
46   - m1: 'Th.1',
47   - m2: 'Th.2',
48   - m3: 'Th.3',
49   - m4: 'Th.4',
50   - m5: 'Th.5',
51   - m6: 'Th.6',
52   - m7: 'Th.7',
53   - m8: 'Th.8',
54   - m9: 'Th.9',
55   - m10: 'Th.10',
56   - m11: 'Th.11',
57   - m12: 'Th.12'
58   - }
59   - },
60   - transfer: {
61   - titles: {
62   - source: 'Nguแป“n',
63   - target: 'ฤรญch'
64   - },
65   - filterPlaceholder: 'Nhแบญp tแปซ khรณa',
66   - notFoundText: 'Khรดng tรฌm thแบฅy'
67   - },
68   - modal: {
69   - okText: 'ฤแป“ng รฝ',
70   - cancelText: 'Hแปงy bแป'
71   - },
72   - poptip: {
73   - okText: 'ฤแป“ng รฝ',
74   - cancelText: 'Hแปงy bแป'
75   - },
76   - page: {
77   - prev: 'Trang trฦฐแป›c',
78   - next: 'Trang kแบฟ',
79   - total: 'Tแป•ng',
80   - item: 'kแบฟt quแบฃ',
81   - items: 'kแบฟt quแบฃ',
82   - prev5: '5 trang trฦฐแป›c',
83   - next5: '5 trang kแบฟ',
84   - page: '/trang',
85   - goto: 'Tแป›i trang',
86   - p: ''
87   - },
88   - rate: {
89   - star: 'Sao',
90   - stars: 'Sao'
91   - },
92   - tree: {
93   - emptyText: 'Khรดng cรณ dแปฏ liแป‡u'
  2 + i: {
  3 + select: {
  4 + placeholder: 'Chแปn',
  5 + noMatch: 'Khรดng tรฌm thแบฅy',
  6 + loading: 'ฤang tแบฃi'
  7 + },
  8 + table: {
  9 + noDataText: 'Khรดng cรณ dแปฏ liแป‡u',
  10 + noFilteredDataText: 'Khรดng cรณ dแปฏ liแป‡u lแปc',
  11 + confirmFilter: 'Xรกc nhแบญn',
  12 + resetFilter: 'Lร m lแบกi',
  13 + clearFilter: 'Xรณa hแบฟt'
  14 + },
  15 + datepicker: {
  16 + selectDate: 'Chแปn ngร y',
  17 + selectTime: 'Chแปn giแป',
  18 + startTime: 'Ngร y bแบฏt ฤ‘แบงu',
  19 + endTime: 'Ngร y kแบฟt thรบc',
  20 + clear: 'Xรณa',
  21 + ok: 'ฤแป“ng รฝ',
  22 + month: '',
  23 + month1: 'Thรกng 1',
  24 + month2: 'Thรกng 2',
  25 + month3: 'Thรกng 3',
  26 + month4: 'Thรกng 4',
  27 + month5: 'Thรกng 5',
  28 + month6: 'Thรกng 6',
  29 + month7: 'Thรกng 7',
  30 + month8: 'Thรกng 8',
  31 + month9: 'Thรกng 9',
  32 + month10: 'Thรกng 10',
  33 + month11: 'Thรกng 11',
  34 + month12: 'Thรกng 12',
  35 + year: '',
  36 + weeks: {
  37 + sun: 'CN',
  38 + mon: 'T2',
  39 + tue: 'T3',
  40 + wed: 'T4',
  41 + thu: 'T5',
  42 + fri: 'T6',
  43 + sat: 'T7'
  44 + },
  45 + months: {
  46 + m1: 'Th.1',
  47 + m2: 'Th.2',
  48 + m3: 'Th.3',
  49 + m4: 'Th.4',
  50 + m5: 'Th.5',
  51 + m6: 'Th.6',
  52 + m7: 'Th.7',
  53 + m8: 'Th.8',
  54 + m9: 'Th.9',
  55 + m10: 'Th.10',
  56 + m11: 'Th.11',
  57 + m12: 'Th.12'
  58 + }
  59 + },
  60 + transfer: {
  61 + titles: {
  62 + source: 'Nguแป“n',
  63 + target: 'ฤรญch'
  64 + },
  65 + filterPlaceholder: 'Nhแบญp tแปซ khรณa',
  66 + notFoundText: 'Khรดng tรฌm thแบฅy'
  67 + },
  68 + modal: {
  69 + okText: 'ฤแป“ng รฝ',
  70 + cancelText: 'Hแปงy bแป'
  71 + },
  72 + poptip: {
  73 + okText: 'ฤแป“ng รฝ',
  74 + cancelText: 'Hแปงy bแป'
  75 + },
  76 + page: {
  77 + prev: 'Trang trฦฐแป›c',
  78 + next: 'Trang kแบฟ',
  79 + total: 'Tแป•ng',
  80 + item: 'kแบฟt quแบฃ',
  81 + items: 'kแบฟt quแบฃ',
  82 + prev5: '5 trang trฦฐแป›c',
  83 + next5: '5 trang kแบฟ',
  84 + page: '/trang',
  85 + goto: 'Tแป›i trang',
  86 + p: ''
  87 + },
  88 + rate: {
  89 + star: 'Sao',
  90 + stars: 'Sao'
  91 + },
  92 + tree: {
  93 + emptyText: 'Khรดng cรณ dแปฏ liแป‡u'
  94 + }
94 95 }
95   - }
96 96 };
... ...
src/styles/components/avatar.less 0 โ†’ 100644
  1 +@avatar-prefix-cls: ~"@{css-prefix}avatar";
  2 +
  3 +.@{avatar-prefix-cls} {
  4 + display: inline-block;
  5 + text-align: center;
  6 + background: @avatar-bg;
  7 + color: @avatar-color;
  8 + white-space: nowrap;
  9 + position: relative;
  10 + overflow: hidden;
  11 +
  12 + .avatar-size(@avatar-size-base, @avatar-font-size-base);
  13 +
  14 + &-large {
  15 + .avatar-size(@avatar-size-lg, @avatar-font-size-lg);
  16 + }
  17 +
  18 + &-small {
  19 + .avatar-size(@avatar-size-sm, @avatar-font-size-sm);
  20 + }
  21 +
  22 + &-square {
  23 + border-radius: @avatar-border-radius;
  24 + }
  25 +
  26 + & > img {
  27 + width: 100%;
  28 + height: 100%;
  29 + }
  30 +}
  31 +
  32 +.avatar-size(@size, @font-size) {
  33 + width: @size;
  34 + height: @size;
  35 + line-height: @size;
  36 + border-radius: @size / 2;
  37 +
  38 + & > * {
  39 + line-height: @size;
  40 + }
  41 +
  42 + &.@{avatar-prefix-cls}-icon {
  43 + font-size: @font-size;
  44 + }
  45 +}
... ...
src/styles/components/color-picker.less 0 โ†’ 100644
  1 +@color-picker-prefix-cls: ~"@{css-prefix}color-picker";
  2 +
  3 +.@{color-picker-prefix-cls} {
  4 + &-rel{
  5 + line-height: 0;
  6 + }
  7 + &-color{
  8 + width: 20px;
  9 + height: 100%;
  10 + border: 1px solid @text-color;
  11 + }
  12 +}
0 13 \ No newline at end of file
... ...
src/styles/components/index.less
... ... @@ -38,4 +38,6 @@
38 38 @import "carousel";
39 39 @import "rate";
40 40 @import "upload";
41   -@import "tree";
42 41 \ No newline at end of file
  42 +@import "tree";
  43 +@import "avatar";
  44 +@import "color-picker";
43 45 \ No newline at end of file
... ...
src/styles/components/radio.less
... ... @@ -6,6 +6,7 @@
6 6 .@{radio-group-prefix-cls} {
7 7 display: inline-block;
8 8 font-size: @font-size-small;
  9 + vertical-align: middle;
9 10 &-vertical{
10 11 .@{radio-prefix-cls}-wrapper {
11 12 display: block;
... ...
src/styles/custom.less
... ... @@ -161,4 +161,15 @@
161 161 @slider-margin : 16px 0;
162 162 @slider-button-wrap-size : 18px;
163 163 @slider-button-wrap-offset : -4px;
164   -@slider-disabled-color : #ccc;
165 164 \ No newline at end of file
  165 +@slider-disabled-color : #ccc;
  166 +
  167 +// Avatar
  168 +@avatar-size-base: 32px;
  169 +@avatar-size-lg: 40px;
  170 +@avatar-size-sm: 24px;
  171 +@avatar-font-size-base: 18px;
  172 +@avatar-font-size-lg: 24px;
  173 +@avatar-font-size-sm: 14px;
  174 +@avatar-bg: #ccc;
  175 +@avatar-color: #fff;
  176 +@avatar-border-radius: @border-radius-small;
166 177 \ No newline at end of file
... ...
test/unit/specs/date-picker.spec.js 0 โ†’ 100644
  1 +import { createVue, destroyVM } from '../util';
  2 +
  3 +describe('DatePicker.vue', () => {
  4 + let vm;
  5 + afterEach(() => {
  6 + destroyVM(vm);
  7 + });
  8 +
  9 + it('should create a DatePicker component and open the calendar with the current month', done => {
  10 + vm = createVue(`
  11 + <Date-Picker></Date-Picker>
  12 + `);
  13 + const picker = vm.$children[0];
  14 + picker.showPicker();
  15 + vm.$nextTick(() => {
  16 + const calendarBody = vm.$el.querySelector('.ivu-picker-panel-body .ivu-date-picker-cells:first-of-type');
  17 + const calendarCells = [...calendarBody.querySelectorAll('.ivu-date-picker-cells-cell')].filter(el => {
  18 + const prevMonth = el.classList.contains('ivu-date-picker-cells-cell-prev-month');
  19 + const nextMonth = el.classList.contains('ivu-date-picker-cells-cell-next-month');
  20 + return !prevMonth && !nextMonth;
  21 + });
  22 + const today = new Date();
  23 + const daysInCurrentMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();
  24 + expect(daysInCurrentMonth).to.equal(calendarCells.length);
  25 + done();
  26 + });
  27 + });
  28 +});
... ...
test/unit/specs/time-spinner.spec.js 0 โ†’ 100644
  1 +import { createVue, destroyVM } from '../util';
  2 +
  3 +describe('TimePicker.vue', () => {
  4 + let vm;
  5 + afterEach(() => {
  6 + destroyVM(vm);
  7 + });
  8 +
  9 + it('should create a TimePicker component with hours, minutes and seconds', done => {
  10 + vm = createVue(`
  11 + <Time-Picker></Time-Picker>
  12 + `);
  13 + const picker = vm.$children[0];
  14 + picker.handleIconClick(); // open the picker panels
  15 +
  16 + vm.$nextTick(() => {
  17 + const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
  18 + expect(spiners.length).to.equal(3); // hh:mm:ss
  19 + expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
  20 + expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
  21 + expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
  22 + done();
  23 + });
  24 + });
  25 +
  26 + it('should create a TimePicker component with only hours and minutes', done => {
  27 + vm = createVue(`
  28 + <Time-Picker format="HH:mm"></Time-Picker>
  29 + `);
  30 + const picker = vm.$children[0];
  31 + picker.handleIconClick(); // open the picker panels
  32 +
  33 + vm.$nextTick(() => {
  34 + const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
  35 + expect([...spiners].filter(el => el.style.display != 'none').length).to.equal(2); // hh:mm
  36 + expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
  37 + expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
  38 + done();
  39 + });
  40 + });
  41 +
  42 + it('should create a TimePicker component with steps of 15 minutes', done => {
  43 + vm = createVue(`
  44 + <Time-Picker :steps="[1, 15]"></Time-Picker>
  45 + `);
  46 + const picker = vm.$children[0];
  47 + picker.handleIconClick(); // open the picker panels
  48 +
  49 + vm.$nextTick(() => {
  50 + const spiners = picker.$el.querySelectorAll('.ivu-time-picker-cells-list');
  51 + const minutesList = [...spiners[1].querySelectorAll('.ivu-time-picker-cells-cell')];
  52 +
  53 + expect(spiners[0].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(24);
  54 + expect(minutesList.map(el => el.textContent).join(',')).to.equal('00,15,30,45');
  55 + expect(spiners[1].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(4);
  56 + expect(spiners[2].querySelectorAll('.ivu-time-picker-cells-cell').length).to.equal(60);
  57 + done();
  58 + });
  59 + });
  60 +});
... ...