Compare commits

...

30 Commits

Author SHA1 Message Date
Jikkai Xiao
38913cd9d4 [release] 2.4.2 2018-06-26 14:52:38 +08:00
Jikkai Xiao
7f1517d2cc [build] 2.4.2 2018-06-26 14:52:38 +08:00
Jikkai Xiao
663cca5e64 Changelog: update for 2.4.2 2018-06-26 13:23:12 +08:00
杨奕
f6df39e8c1 Loading: add missing definition of directive (#11749) 2018-06-26 11:31:17 +08:00
Jiewei Qian
5c44539de1 DatePicker: guards common but incorrect usage (#11673) 2018-06-25 16:47:45 +08:00
王锦辉
8f9986f83c Chore: eslint ignore font files (#11696) 2018-06-25 16:35:58 +08:00
Jikkai Xiao
ef98b75aff Tabs: add activeName and oldActiveName parameters to before-leave hook (#11713)
* Tabs: add activeName and oldActiveName parameters to before-leave hook

* Tabs: fix docs
2018-06-25 15:59:49 +08:00
Jaak Asser
8397e12d1a i18n: update ee.js (#11709)
Add missing Estonian translations
2018-06-25 13:30:12 +08:00
kratsstark
9355bd3180 Select: remove empty option item when default value is null in single mode (#11731) 2018-06-25 12:27:04 +08:00
Geass
43191961f6 Docs: fix link of element react (#11718) 2018-06-22 19:02:31 +08:00
Jikkai Xiao
97a72d3af6 Table: fix highlightCurrentRow regression (#11691) 2018-06-21 16:14:06 +08:00
Jiewei Qian
0ed8d18603 Select: fix form change validation (#11672) 2018-06-20 11:15:34 +08:00
Jikkai Xiao
1f24f2abae Chore: add missing file when create new component (#11663) 2018-06-19 13:17:47 +08:00
Jikkai Xiao
7199da9836 Menu: fix open method error when collapse is changed (#11646) 2018-06-15 17:39:45 +08:00
杨奕
475f7cf01d Autocomplete: passes id to nested native input (#11643) 2018-06-15 12:30:51 +08:00
hetech
85e562185e Chore: delete unused file (#11641) 2018-06-15 12:20:19 +08:00
mengro
23a2e8d9ee Pagination: use setCurrentValue when reassigning input value (#11608)
* Pagination:  input bug

currentValue in input component's data object didn't refresh when changeHandle emited

* Update pagination.js
2018-06-15 11:44:09 +08:00
杨奕
48c7bcc933 Tree: optimize not-allowed dropping cursor (#11631) 2018-06-14 18:14:39 +08:00
hetech
7bee91a517 Cascader: close when option clicked (#11623)
* Cascader: close when option clicked in hover mode

* update menu.vue
2018-06-14 17:50:10 +08:00
Jikkai Xiao
25ffe8c97e Table: fix class-name & label-class-name prop not reactive (#11626) 2018-06-14 17:07:00 +08:00
杨奕
dd3bb2ce20 Pagination: add size to nested select (#11622) 2018-06-14 11:20:29 +08:00
杨奕
0178893db1 Chore: update sponsor, optimize suggestJump (#11614) 2018-06-13 17:51:42 +08:00
杨奕
671c42c610 Button: fix style of single round/circle button in a group (#11605) 2018-06-13 13:46:34 +08:00
sjaustirni
c1b580583a i18n: update Slovak translation (#11597) 2018-06-13 10:43:06 +08:00
hetech
bdd95cf962 Cascader: not focus when outside clicked (#11588) 2018-06-12 19:24:09 +08:00
杨奕
e58cffaaa1 Table: fix highlightCurrentRow regression (#11563) 2018-06-10 20:44:59 +08:00
Gonzalo Nandez
af1a287cf3 Docs: update es changelog for 2.4.1 (#11546) 2018-06-10 20:41:03 +08:00
Akiho Nagao
db928dedea Popover: fix reference error in the loop (#11503)
* Popover: fix reference error in the loop

* Update directive.js
2018-06-08 19:13:49 +08:00
Jikkai Xiao
35931815fc Test: add more test cases (#11541)
* Tabs: improve test case

* Container: improve test case

* Radio: improve test case
2018-06-08 15:59:24 +08:00
Jikkai Xiao
23de28bd4b Tabs: fix tabs style (#11536) 2018-06-08 15:54:55 +08:00
47 changed files with 403 additions and 329 deletions

View File

@@ -7,3 +7,5 @@ lib
coverage
*.md
*.scss
*.woff
*.ttf

View File

@@ -1,5 +1,19 @@
## Changelog
### 2.4.2
*2018-06-26*
- Now `class-name` and `label-class-name` of Table are reactive, #11626
- Fixed Table still highlighting clicked row when `highlight-current-row` is `false`, #11646
- Fixed a style bug of ButtonGroup when it has only one `round` or `circle` Button, #11605
- Fixed style of page size Select of Pagination, #11622
- Fixed Menu's `open` method error when `collapse` is dynamically changed, #11646
- Added `activeName` and `oldActiveName` parameters to the before-leave hook of Tabs, #11713
- Fixed Cascader focused after outside clicked, #11588
- Fixed Cascader not closing when option is clicked when `change-on-select` is true, #11623
- Now updating Select's value programmatically will trigger form validation, #11672
### 2.4.1
*2018-06-08*

View File

@@ -1,21 +1,35 @@
## Changelog
### 2.4.2
*2018-06-26*
- Now `class-name` and `label-class-name` of Table are reactive, #11626
- Fixed Table still highlighting clicked row when `highlight-current-row` is `false`, #11646
- Fixed a style bug of ButtonGroup when it has only one `round` or `circle` Button, #11605
- Fixed style of page size Select of Pagination, #11622
- Fixed Menu's `open` method error when `collapse` is dynamically changed, #11646
- Added `activeName` and `oldActiveName` parameters to the before-leave hook of Tabs, #11713
- Fixed Cascader focused after outside clicked, #11588
- Fixed Cascader not closing when option is clicked when `change-on-select` is true, #11623
- Now updating Select's value programmatically will trigger form validation, #11672
### 2.4.1
*2018-06-08*
- Removed Autocomplete's duplicate type declaration, #11388
- Fixed Select's dropdown arrow style in FireFox when nested in Form, #11427
- Fixed clear icon of Select still showing when the initial value is `null`, #11460
- Fixed disabled radio showing box-shadow when clicked, #11462
- Added `iconClass` attribute for MessageBox, #11499
- Added `stretch` attribute for Tabs, #11476
- Fixed rendering order issue of TabPane when Tabs is `lazy`, #11461
- Fixed Table not retaining current highlight row when expanded, #11464
- Fixed focusing state when `before-leave` returns a resolved promise, #11386
- Fixed disabled Popover still creating poppers, #11426
- Fixed Tree's endless loop when a new node is added in lazy mode, #11430 (by @wangjingf)
- Added `closed` event for Dialog, #11490
- Removida la declaración duplicada de type en Autocompletar, #11388
- Corregido el estilo de flecha en el dropdown de Select en FireFox cuando se anidaba en el formulario, #11427
- Corregido que el ícono `clear` de Select seguia apareciendo cuando el valor inicial era `null`, #11460
- Arreglado que cuando el radio estaba `disabled` mostraba el box-shadow al hacer click, #11462
- Añadido el atributo `iconClass` para MessageBox, #11499
- Añadido el atributo `stretch` para Tabs, #11476
- Arreglado el problema de orden de renderizado de TabPane cuando Tabs es `lazy`, #11461
- Arreglado que Table no retenia la fila actual de resaltados cuando se expandia, #11464
- Arreglado que focusing state cuando `before-leave` devolvia una promesa resuelta, #11386
- Arreglado que Popover deshabilitado seguia creando poppers, #11426
- Arreglado el bucle sin fin de Tree cuando se añadia un nuevo nodo en modo `lazy`, #11430 (por @wangjingf)
- Añadido el evento `closed` para Dialog, #11490
### 2.4.0 Fullerene

View File

@@ -1,5 +1,19 @@
## 更新日志
### 2.4.2
*2018-06-26*
- 修复 Table 的 `class-name``label-class-name` 属性不支持动态更新的问题,#11626
- 修复 Table 在 `highlight-current-row``false` 时点击行也会触发高亮的问题,#11691 #11563
- 修复 ButtonGroup 中只有一个 `round``circle` 的 Button 时的样式错误,#11605
- 修复在某些情况下 Pagination 的条目数选择器的样式错误,#11622
- 修复 Menu 的 `collapse` 属性变化后无法使用 `open` 方法的问题,#11646
- Tabs 的 `before-leave` 钩子添加了 `activeName``oldActiveName` 参数,#11713
- 修复 Cascader 关闭后的聚焦问题,#11588
- 修复 Cascader 在 `change-on-select` 状态下点击选项不关闭的问题,#11623
- 现在通过代码改变 Select 的值后会触发表单校验,与 Input 行为一致,#11672
### 2.4.1
*2018-06-08*

View File

@@ -57,6 +57,11 @@
<img width="150px" src="https://user-images.githubusercontent.com/10095631/35603534-bb24470c-0678-11e8-8bcc-17ceaef8cbef.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://bitsrc.io/" target="_blank">
<img width="150px" src="https://user-images.githubusercontent.com/10095631/41342907-e44e7196-6f2f-11e8-92f2-47702dc8f059.png">
</a>
</td>
</tr>
</tbody>
</table>
@@ -72,7 +77,7 @@
- [FAQ](./FAQ.md)
- [Customize theme](http://element.eleme.io/#/en-US/component/custom-theme)
- [Preview and generate theme online](https://elementui.github.io/theme-chalk-preview)
- [Element for React](https://github.com/eleme/element-react)
- [Element for React](https://github.com/elemefe/element-react)
- [Element for Angular](https://github.com/ElemeFE/element-angular)
- [Atom helper](https://github.com/ElemeFE/element-helper)
- [Visual Studio Code helper](https://github.com/ElemeFE/vscode-element-helper)

View File

@@ -66,6 +66,22 @@ describe('${ComponentName}', () => {
});
});
`
},
{
filename: path.join('../../packages/theme-chalk/src', `${componentname}.scss`),
content: `@import "mixins/mixins";
@import "common/var";
@include b(${componentname}) {
}`
},
{
filename: path.join('../../types', `${componentname}.d.ts`),
content: `import { ElementUIComponent } from './component'
/** ${ComponentName} Component */
export declare class El${ComponentName} extends ElementUIComponent {
}`
}
];

View File

@@ -231,7 +231,7 @@
const href = location.href;
const preferGithub = localStorage.getItem('PREFER_GITHUB');
if (href.indexOf('element-cn') > -1 || preferGithub) return;
if (href.indexOf('element-cn') > -1 || href.indexOf('element.faas') > -1 || preferGithub) return;
setTimeout(() => {
if (this.lang !== 'zh-CN') return;
this.$confirm('建议大陆用户访问部署在国内的站点,是否跳转?', '提示')

View File

@@ -9,7 +9,7 @@
<a href="https://github.com/ElementUI/element-starter" class="footer-main-link" target="_blank">{{ langConfig.starter }}</a>
<a href="https://github.com/ElementUI/element-theme" class="footer-main-link" target="_blank">{{ langConfig.theme }}</a>
<a href="https://github.com/ElementUI/theme-chalk-preview" class="footer-main-link" target="_blank">{{ langConfig.preview }}</a>
<a href="https://github.com/eleme/element-react" class="footer-main-link" target="_blank">Element-React</a>
<a href="https://github.com/elemefe/element-react" class="footer-main-link" target="_blank">Element-React</a>
<a href="https://github.com/ElemeFE/element-angular" class="footer-main-link" target="_blank">Element-Angular</a>
</div>
<div class="footer-main">

View File

@@ -377,7 +377,7 @@ Only card type Tabs support addable & closeable.
| value | name of the selected tab | string | — | name of first tab |
| tab-position | position of tabs | string | top/right/bottom/left | top |
| stretch | whether width of tab automatically fits its container | boolean | - | false |
| before-leave | hook function before switching tab. If `false` is returned or a `Promise` is returned and then is rejected, switching will be prevented | function | — | — |
| before-leave | hook function before switching tab. If `false` is returned or a `Promise` is returned and then is rejected, switching will be prevented | Function(activeName, oldActiveName) | — | — |
### Tabs Events
| Event Name | Description | Parameters |

View File

@@ -318,4 +318,5 @@ Si la variable ligada a `visible` se gestiona en el Vuex store, el `.sync` no pu
| ---------------- | ---------------------------------------- | ---------- |
| open | se activa cuando se abre el cuadro de Diálogo | — |
| close | se dispara cuando el Diálogo se cierra | — |
| closed | triggers when the Dialog closing animation ends | — |
| closed | se activa cuando finaliza la animación de cierre del Diálog | — |

View File

@@ -376,8 +376,8 @@ Solo las pestañas de tipo tarjeta soportan adición y cierre.
| editable | si la Pestaña es añadible y cerrable | boolean | — | false |
| value | nombre de la pestaña seleccionada | string | — | nombre de la primer pestaña |
| tab-position | posición de tabulación | string | top/right/bottom/left | top |
| stretch | whether width of tab automatically fits its container | boolean | - | false |
| before-leave | función `hook` antes de cambiar de pestaña. Si se devuelve `false` o se devuelve una `Promise` y luego se rechaza, se evitará el cambio. | function | — | — |
| stretch | si el ancho del tab se ajusta automáticamente a su contenedor | boolean | - | false |
| before-leave | función `hook` antes de cambiar de pestaña. Si se devuelve `false` o se devuelve una `Promise` y luego se rechaza, se evitará el cambio. | Function(activeName, oldActiveName) | — | — |
### Eventos de Pestañas
| Nombre de Evento | Descripción | Parámetros |

View File

@@ -375,7 +375,7 @@
| value | 绑定值,选中选项卡的 name | string | — | 第一个选项卡的 name |
| tab-position | 选项卡所在位置 | string | top/right/bottom/left | top |
| stretch | 标签的宽度是否自撑开 | boolean | - | false |
| before-leave | 切换标签之前的钩子,若返回 false 或者返回 Promise 且被 reject则阻止切换。 | function | — | — |
| before-leave | 切换标签之前的钩子,若返回 false 或者返回 Promise 且被 reject则阻止切换。 | Function(activeName, oldActiveName) | — | — |
### Tabs Events
| 事件名称 | 说明 | 回调参数 |

View File

@@ -263,7 +263,7 @@
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf('三级 3-1-1') === -1;
return draggingNode.data.label.indexOf('三级 3-2-2') === -1;
},
loadNode(node, resolve) {
if (node.level === 0) {
@@ -1173,7 +1173,7 @@
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf('三级 3-1-1') === -1;
return draggingNode.data.label.indexOf('三级 3-2-2') === -1;
}
}
};

View File

@@ -6,7 +6,7 @@
},
{
"name": "Element React",
"href": "https://eleme.github.io/element-react/"
"href": "https://elemefe.github.io/element-react/"
},
{
"name": "Element Angular",
@@ -256,7 +256,7 @@
},
{
"name": "Element React",
"href": "https://eleme.github.io/element-react/"
"href": "https://elemefe.github.io/element-react/"
},
{
"name": "Element Angular",
@@ -506,7 +506,7 @@
},
{
"name": "Element React",
"href": "https://eleme.github.io/element-react/"
"href": "https://elemefe.github.io/element-react/"
},
{
"name": "Element Angular",

View File

@@ -1 +1 @@
{"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.1":"2.4"}
{"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.2":"2.4"}

View File

@@ -1,6 +1,6 @@
{
"name": "element-ui",
"version": "2.4.1",
"version": "2.4.2",
"description": "A Component Library for Vue.js.",
"main": "lib/element-ui.common.js",
"files": [

View File

@@ -9,7 +9,7 @@
>
<el-input
ref="input"
v-bind="$props"
v-bind="[$props, $attrs]"
@input="handleChange"
@focus="handleFocus"
@blur="handleBlur"
@@ -17,7 +17,6 @@
@keydown.down.native.prevent="highlight(highlightedIndex + 1)"
@keydown.enter.native="handleKeyEnter"
@keydown.native.tab="close"
:label="label"
>
<template slot="prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
@@ -70,6 +69,8 @@
mixins: [Emitter, Focus('input'), Migrating],
inheritAttrs: false,
componentName: 'ElAutocomplete',
components: {

View File

@@ -48,7 +48,7 @@
<template v-if="showAllLevels">
<template v-for="(label, index) in currentLabels">
{{ label }}
<span v-if="index < currentLabels.length - 1"> {{ separator }} </span>
<span v-if="index < currentLabels.length - 1" :key="index"> {{ separator }} </span>
</template>
</template>
<template v-else>
@@ -178,7 +178,9 @@ export default {
menuVisible: false,
inputHover: false,
inputValue: '',
flatOptions: null
flatOptions: null,
id: generateId(),
needFocus: true
};
},
@@ -215,9 +217,6 @@ export default {
},
cascaderDisabled() {
return this.disabled || (this.elForm || {}).disabled;
},
id() {
return generateId();
}
},
@@ -280,7 +279,11 @@ export default {
hideMenu() {
this.inputValue = '';
this.menu.visible = false;
this.$refs.input.focus();
if (this.needFocus) {
this.$refs.input.focus();
} else {
this.needFocus = true;
}
},
handleActiveItemChange(value) {
this.$nextTick(_ => {
@@ -386,7 +389,10 @@ export default {
ev.stopPropagation();
this.handlePick([], true);
},
handleClickoutside() {
handleClickoutside(pickFinished = false) {
if (this.menuVisible && !pickFinished) {
this.needFocus = false;
}
this.menuVisible = false;
},
handleClick() {

View File

@@ -42,7 +42,8 @@
changeOnSelect: false,
popperClass: '',
hoverTimer: 0,
clicking: false
clicking: false,
id: generateId()
};
},
@@ -97,9 +98,6 @@
formatOptions(optionsCopy);
return loadActiveOptions(optionsCopy);
}
},
id() {
return generateId();
}
},
@@ -240,6 +238,13 @@
});
};
events.on[triggerEvent] = triggerHandler;
if (triggerEvent === 'mouseenter' && this.changeOnSelect) {
events.on.click = () => {
if (this.activeValue.indexOf(item.value) !== -1) {
this.$emit('closeInside', true);
}
};
}
events.on['mousedown'] = () => {
this.clicking = true;
};

View File

@@ -508,12 +508,21 @@ export default {
},
parsedValue() {
const isParsed = isDateObject(this.value) || (Array.isArray(this.value) && this.value.every(isDateObject));
if (this.valueFormat && !isParsed) {
return parseAsFormatAndType(this.value, this.valueFormat, this.type, this.rangeSeparator) || this.value;
} else {
if (!this.value) return this.value; // component value is not set
if (this.type === 'time-select') return this.value; // time-select does not require parsing, this might change in next major version
const valueIsDateObject = isDateObject(this.value) || (Array.isArray(this.value) && this.value.every(isDateObject));
if (valueIsDateObject) {
return this.value;
}
if (this.valueFormat) {
return parseAsFormatAndType(this.value, this.valueFormat, this.type, this.rangeSeparator) || this.value;
}
// NOTE: deal with common but incorrect usage, should remove in next major version
// user might provide string / timestamp without value-format, coerce them into date (or array of date)
return Array.isArray(this.value) ? this.value.map(val => new Date(val)) : new Date(this.value);
},
_elFormItemSize() {

View File

@@ -66,16 +66,14 @@
menuItems: null,
menuItemsArray: null,
dropdownElm: null,
focusing: false
focusing: false,
listId: `dropdown-menu-${generateId()}`
};
},
computed: {
dropdownSize() {
return this.size || (this.$ELEMENT || {}).size;
},
listId() {
return `dropdown-menu-${generateId()}`;
}
},

View File

@@ -229,8 +229,6 @@
}
},
created() {
this.parentMenu.addSubmenu(this);
this.rootMenu.addSubmenu(this);
this.$on('toggle-collapse', this.handleCollapseToggle);
this.$on('mouse-enter-child', () => {
this.mouseInChild = true;
@@ -242,6 +240,8 @@
});
},
mounted() {
this.parentMenu.addSubmenu(this);
this.rootMenu.addSubmenu(this);
this.initPopper();
},
beforeDestroy() {

View File

@@ -179,6 +179,7 @@ export default {
<el-select
value={ this.$parent.internalPageSize }
popperClass={ this.$parent.popperClass || '' }
size="mini"
on-input={ this.handleChange }
disabled={ this.$parent.disabled }>
{
@@ -252,15 +253,16 @@ export default {
const num = parseInt(value, 10);
if (!isNaN(num)) {
if (num < 1) {
this.$refs.input.$el.querySelector('input').value = 1;
this.$refs.input.setCurrentValue(1);
} else {
this.reassignMaxValue(value);
}
}
},
reassignMaxValue(value) {
if (+value > this.$parent.internalPageCount) {
this.$refs.input.$el.querySelector('input').value = this.$parent.internalPageCount;
var internalPageCount = this.$parent.internalPageCount;
if (+value > internalPageCount) {
this.$refs.input.setCurrentValue(internalPageCount);
}
}
},

View File

@@ -2,7 +2,11 @@ const getReference = (el, binding, vnode) => {
const _ref = binding.expression ? binding.value : binding.arg;
const popper = vnode.context.$refs[_ref];
if (popper) {
popper.$refs.reference = el;
if (Array.isArray(popper)) {
popper[0].$refs.reference = el;
} else {
popper.$refs.reference = el;
}
}
};

View File

@@ -339,7 +339,7 @@
this.cachedPlaceHolder = this.currentPlaceholder = val;
},
value(val) {
value(val, oldVal) {
if (this.multiple) {
this.resetInputHeight();
if (val.length > 0 || (this.$refs.input && this.query !== '')) {
@@ -356,6 +356,9 @@
if (this.filterable && !this.multiple) {
this.inputLength = 20;
}
if (!valueEquals(val, oldVal)) {
this.dispatch('ElFormItem', 'el.form.change', val);
}
},
visible(val) {
@@ -503,13 +506,14 @@
emitChange(val) {
if (!valueEquals(this.value, val)) {
this.$emit('change', val);
this.dispatch('ElFormItem', 'el.form.change', val);
}
},
getOption(value) {
let option;
const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]';
const isNull = Object.prototype.toString.call(value).toLowerCase() === '[object null]';
for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
const cachedOption = this.cachedOptions[i];
const isEqual = isObject
@@ -521,7 +525,7 @@
}
}
if (option) return option;
const label = !isObject
const label = (!isObject && !isNull)
? value : '';
let newOption = {
value: value,

View File

@@ -268,7 +268,9 @@ export default {
getRowClass(row, rowIndex) {
const currentRow = this.store.states.currentRow;
const classes = currentRow === row ? ['el-table__row', 'current-row'] : ['el-table__row'];
const classes = this.table.highlightCurrentRow && currentRow === row
? ['el-table__row', 'current-row']
: ['el-table__row'];
if (this.stripe && rowIndex % 2 === 1) {
classes.push('el-table__row--striped');

View File

@@ -405,6 +405,18 @@ export default {
if (this.columnConfig) {
this.columnConfig.formatter = newVal;
}
},
className(newVal) {
if (this.columnConfig) {
this.columnConfig.className = newVal;
}
},
labelClassName(newVal) {
if (this.columnConfig) {
this.columnConfig.labelClassName = newVal;
}
}
},

View File

@@ -193,10 +193,10 @@ TableStore.prototype.mutations = {
changeSortCondition(states, options) {
states.data = sortData((states.filteredData || states._data || []), states);
const el = this.table.$el;
if (el) {
const { $el, highlightCurrentRow } = this.table;
if ($el && highlightCurrentRow) {
const data = states.data;
const tr = el.querySelector('tbody').children;
const tr = $el.querySelector('tbody').children;
const rows = [].filter.call(tr, row => hasClass(row, 'el-table__row'));
const row = rows[data.indexOf(states.currentRow)];

View File

@@ -249,7 +249,7 @@
{scrollBtn}
<div class={['el-tabs__nav-scroll']} ref="navScroll">
<div
class={['el-tabs__nav', stretch && ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'is-stretch' : '']}
class={['el-tabs__nav', `is-${ this.rootTabs.tabPosition }`, stretch && ['top', 'bottom'].indexOf(this.rootTabs.tabPosition) !== -1 ? 'is-stretch' : '']}
ref="nav"
style={navStyle}
role="tablist"
@@ -278,4 +278,3 @@
}
};
</script>

View File

@@ -74,7 +74,7 @@
this.$emit('input', value);
};
if (this.currentName !== value && this.beforeLeave) {
const before = this.beforeLeave();
const before = this.beforeLeave(value, this.currentName);
if (before && before.then) {
before.then(() => {
changeCurrentName();

View File

@@ -1,6 +1,6 @@
{
"name": "element-theme-chalk",
"version": "2.4.1",
"version": "2.4.2",
"description": "Element component chalk theme.",
"main": "lib/index.css",
"style": "lib/index.css",

View File

@@ -206,6 +206,14 @@
border-bottom-right-radius: $--button-border-radius;
border-top-left-radius: $--button-border-radius;
border-bottom-left-radius: $--button-border-radius;
&.is-round {
border-radius: 20px;
}
&.is-circle {
border-radius: 50%;
}
}
&:not(:first-child):not(:last-child) {
border-radius: 0;

View File

@@ -40,7 +40,6 @@
.el-input__inner {
padding-right: 25px;
border-radius: $--pagination-border-radius;
height: $--pagination-button-height;
}
}

View File

@@ -307,6 +307,27 @@
.el-tabs__nav-wrap.is-right {
margin-bottom: 0;
> .el-tabs__nav-prev,
> .el-tabs__nav-next {
height: 30px;
line-height: 30px;
width: 100%;
text-align: center;
cursor: pointer;
i {
transform: rotateZ(90deg);
}
}
> .el-tabs__nav-prev {
left: auto;
top: 0;
}
> .el-tabs__nav-next {
right: auto;
bottom: 0;
}
&.is-scrollable {
padding: 30px 0;
}
@@ -319,34 +340,14 @@
}
}
.el-tabs__nav {
.el-tabs__nav.is-left,
.el-tabs__nav.is-right {
float: none;
}
.el-tabs__item.is-left,
.el-tabs__item.is-right {
display: block;
}
.el-tabs__nav-prev,
.el-tabs__nav-next {
height: 30px;
line-height: 30px;
width: 100%;
text-align: center;
cursor: pointer;
i {
transform: rotateZ(90deg);
}
}
.el-tabs__nav-prev {
left: auto;
top: 0;
}
.el-tabs__nav-next {
right: auto;
bottom: 0;
}
}
@include m(left) {
.el-tabs__header.is-left {

View File

@@ -362,12 +362,12 @@
let dropPrev = true;
let dropInner = true;
let dropNext = true;
let userAllowDropInner = true;
if (typeof this.allowDrop === 'function') {
dropPrev = this.allowDrop(draggingNode.node, dropNode.node, 'prev');
dropInner = this.allowDrop(draggingNode.node, dropNode.node, 'inner');
userAllowDropInner = dropInner = this.allowDrop(draggingNode.node, dropNode.node, 'inner');
dropNext = this.allowDrop(draggingNode.node, dropNode.node, 'next');
}
dragState.allowDrop = dropInner;
event.dataTransfer.dropEffect = dropInner ? 'move' : 'none';
if ((dropPrev || dropInner || dropNext) && oldDropNode !== dropNode) {
if (oldDropNode) {
@@ -399,8 +399,8 @@
const treePosition = this.$el.getBoundingClientRect();
let dropType;
const prevPercent = dropPrev ? (dropInner ? 0.25 : (dropNext ? 0.5 : 1)) : -1;
const nextPercent = dropNext ? (dropInner ? 0.75 : (dropPrev ? 0.5 : 0)) : 1;
const prevPercent = dropPrev ? (dropInner ? 0.25 : (dropNext ? 0.45 : 1)) : -1;
const nextPercent = dropNext ? (dropInner ? 0.75 : (dropPrev ? 0.55 : 0)) : 1;
let indicatorTop = -9999;
const distance = event.clientY - targetPosition.top;
@@ -430,6 +430,7 @@
}
dragState.showDropIndicator = dropType === 'before' || dropType === 'after';
dragState.allowDrop = dragState.showDropIndicator || userAllowDropInner;
dragState.dropType = dropType;
this.$emit('node-drag-over', draggingNode.node, dropNode.node, event);
});

View File

@@ -172,7 +172,7 @@ if (typeof window !== 'undefined' && window.Vue) {
}
module.exports = {
version: '2.4.1',
version: '2.4.2',
locale: locale.use,
i18n: locale.i18n,
install,

View File

@@ -16,10 +16,10 @@ export default {
startTime: 'Algusaeg',
endDate: 'Lõpukuupäev',
endTime: 'Lõpuaeg',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
prevYear: 'Eelmine aasta',
nextYear: 'Järgmine aasta',
prevMonth: 'Eelmine kuu',
nextMonth: 'Järgmine kuu',
year: '',
month1: 'Jaanuar',
month2: 'Veebruar',
@@ -82,7 +82,7 @@ export default {
error: 'Vigane sisend'
},
upload: {
deleteTip: 'press delete to remove', // to be translated
deleteTip: 'Vajuta kustuta et eemaldada',
delete: 'Kustuta',
preview: 'Eelvaate',
continue: 'Jätka'

View File

@@ -16,10 +16,10 @@ export default {
startTime: 'Čas začiatku',
endDate: 'Dátum konca',
endTime: 'Čas konca',
prevYear: 'Previous Year', // to be translated
nextYear: 'Next Year', // to be translated
prevMonth: 'Previous Month', // to be translated
nextMonth: 'Next Month', // to be translated
prevYear: 'Predošlý rok',
nextYear: 'Ďalší rok',
prevMonth: 'Predošlý mesiac',
nextMonth: 'Ďalší mesiac',
day: 'Deň',
week: 'Týždeň',
month: 'Mesiac',
@@ -84,7 +84,7 @@ export default {
error: 'Neplatný vstup'
},
upload: {
deleteTip: 'press delete to remove', // to be translated
deleteTip: 'pre odstránenie stisni klávesu Delete',
delete: 'Vymazať',
preview: 'Prehliadať',
continue: 'Pokračovať'

View File

@@ -1,54 +0,0 @@
const SYNC_HOOK_PROP = '$v-sync';
/**
* v-sync directive
*
* Usage:
* v-sync:component-prop="context prop name"
*
* If your want to sync component's prop "visible" to context prop "myVisible", use like this:
* v-sync:visible="myVisible"
*/
export default {
bind(el, binding, vnode) {
const context = vnode.context;
const component = vnode.child;
const expression = binding.expression;
const prop = binding.arg;
if (!expression || !prop) {
console.warn('v-sync should specify arg & expression, for example: v-sync:visible="myVisible"');
return;
}
if (!component || !component.$watch) {
console.warn('v-sync is only available on Vue Component');
return;
}
const unwatchContext = context.$watch(expression, (val) => {
component[prop] = val;
});
const unwatchComponent = component.$watch(prop, (val) => {
context[expression] = val;
});
Object.defineProperty(component, SYNC_HOOK_PROP, {
value: {
unwatchContext,
unwatchComponent
},
enumerable: false
});
},
unbind(el, binding, vnode) {
const component = vnode.child;
if (component && component[SYNC_HOOK_PROP]) {
const { unwatchContext, unwatchComponent } = component[SYNC_HOOK_PROP];
unwatchContext && unwatchContext();
unwatchComponent && unwatchComponent();
}
}
};

View File

@@ -538,6 +538,76 @@ describe('Cascader', () => {
});
}, 300);
});
it('hover and select', done => {
vm = createVue({
template: `
<el-cascader
ref="cascader"
placeholder="请选择"
:options="options"
expand-trigger="hover"
change-on-select
v-model="selectedOptions"
></el-cascader>
`,
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake'
}]
}, {
value: 'ningbo',
label: 'NingBo',
children: [{
value: 'jiangbei',
label: 'Jiang Bei'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men'
}]
}]
}],
selectedOptions: []
};
}
}, true);
vm.$el.click();
vm.$nextTick(() => {
const menu = vm.$refs.cascader.menu;
const menuElm = menu.$el;
const item1 = menuElm.querySelector('.el-cascader-menu__item');
triggerEvent(item1, 'mouseenter');
menu.$nextTick(() => {
expect(vm.selectedOptions[0]).to.be.equal('zhejiang');
const spy = sinon.spy();
menu.$on('closeInside', spy);
item1.click();
menu.$nextTick(() => {
expect(spy.calledWith(true)).to.be.true;
expect(menu.visible).to.be.false;
done();
});
});
});
});
it('filterable', done => {
vm = createVue({
template: `

View File

@@ -27,6 +27,28 @@ describe('Container', () => {
}, true);
expect(vm.$children[0].$el.classList.contains('is-vertical')).to.true;
});
it('direction', done => {
vm = createVue({
template: `
<el-container :direction="direction">
<el-header></el-header>
<el-main></el-main>
</el-container>
`,
data() {
return {
direction: 'horizontal'
};
}
}, true);
expect(vm.$children[0].$el.classList.contains('is-vertical')).not.to.true;
vm.direction = 'vertical';
vm.$nextTick(() => {
expect(vm.$children[0].$el.classList.contains('is-vertical')).to.true;
done();
});
});
});
describe('Header', () => {

View File

@@ -380,15 +380,19 @@ describe('Form', () => {
expect(valid).to.false;
setTimeout(_ => {
expect(field.validateMessage).to.equal('请选择活动区域');
// programatic modification of bound value does not triggers change validation
// programatic modification triggers change validation
vm.form.region = 'shanghai';
setTimeout(_ => {
expect(field.validateMessage).to.equal('请选择活动区域');
// user modification of bound value triggers change validation
vm.$refs.opt.$el.click();
expect(field.validateMessage).to.equal('');
vm.form.region = '';
setTimeout(_ => {
expect(field.validateMessage).to.equal('');
done();
expect(field.validateMessage).to.equal('请选择活动区域');
// user modification of bound value triggers change validation
vm.$refs.opt.$el.click();
setTimeout(_ => {
expect(field.validateMessage).to.equal('');
done();
}, 100);
}, 100);
}, 100);
}, 100);

View File

@@ -1,4 +1,4 @@
import { createVue, destroyVM } from '../util';
import { createVue, destroyVM, triggerKeyDown } from '../util';
describe('Radio', () => {
let vm;
@@ -258,6 +258,46 @@ describe('Radio', () => {
done();
}, 10);
});
it('keyboard event', done => {
vm = createVue({
template: `
<el-radio-group v-model="radio">
<el-radio-button ref="radio1" :label="3">备选项</el-radio-button>
<el-radio-button ref="radio2" :label="6">备选项</el-radio-button>
<el-radio-button ref="radio3" :label="9">备选项</el-radio-button>
</el-radio-group>
`,
data() {
return {
radio: 6
};
}
}, true);
expect(vm.radio).to.be.equal(6);
vm.$nextTick(() => {
triggerKeyDown(vm.$refs.radio2.$el, 37);
expect(vm.radio).to.be.equal(3);
triggerKeyDown(vm.$refs.radio1.$el, 37);
expect(vm.radio).to.be.equal(9);
vm.$nextTick(() => {
triggerKeyDown(vm.$refs.radio3.$el, 39);
expect(vm.radio).to.be.equal(3);
triggerKeyDown(vm.$refs.radio1.$el, 39);
expect(vm.radio).to.be.equal(6);
vm.$nextTick(() => {
triggerKeyDown(vm.$refs.radio1.$el, 13);
expect(vm.radio).to.be.equal(6);
done();
});
});
});
});
describe('Radio Button', () => {
it('create', done => {
vm = createVue({

View File

@@ -1,163 +0,0 @@
import { createVue, triggerEvent } from '../util';
import Sync from 'element-ui/src/utils/sync';
const Test = {
template: `<div class="sync-test" v-show="visible">
<button @click="visible = false">Hide</button>
A test component.
</div>`,
data() {
return {
visible: true
};
}
};
describe('Sync', () => {
it('should not throw when use incorrectly', () => {
sinon.stub(window.console, 'warn');
createVue({
template: `
<test v-sync>
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
});
expect(window.console.warn.callCount).to.equal(1);
createVue({
template: `
<test v-sync:visible>
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
});
expect(window.console.warn.callCount).to.equal(2);
createVue({
template: `
<test v-sync.visible>
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
});
expect(window.console.warn.callCount).to.equal(3);
createVue({
template: `
<div v-sync:visible="myVisible">
</div>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
});
expect(window.console.warn.callCount).to.equal(4);
window.console.warn.restore();
});
it('context variable should change when inner component variable change', (done) => {
const vm = createVue({
template: `
<test v-sync:visible="myVisible">
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
}, true);
triggerEvent(vm.$el.querySelector('.sync-test button'), 'click', {});
setTimeout(() => {
expect(vm.myVisible).to.be.false;
done();
}, 10);
});
it('inner component variable should change when context variable change', (done) => {
const vm = createVue({
template: `
<test ref="test" v-sync:visible="myVisible">
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true
};
}
}, true);
vm.myVisible = false;
setTimeout(() => {
expect(vm.$refs.test.visible).to.be.false;
expect(vm.$refs.test.$el.style.display).to.equal('none');
done();
}, 10);
});
it('should unwatch expression after destroy', () => {
const vm = createVue({
template: `
<test ref="test" v-sync:visible="myVisible" v-if="createTest">
</test>
`,
components: { Test },
directives: { Sync },
data() {
return {
myVisible: true,
createTest: false
};
}
});
const beforeBindCount = vm._watchers.length;
vm.createTest = true;
const delay = 50;
setTimeout(() => {
const afterBindCount = vm._watchers.length;
expect(afterBindCount).to.be.equal(beforeBindCount + 1);
vm.createTest = false;
setTimeout(() => {
const afterDestroyCount = vm._watchers.length;
expect(afterDestroyCount).to.be.equal(beforeBindCount);
}, delay);
}, delay);
});
});

View File

@@ -1,4 +1,4 @@
import { createVue, destroyVM } from '../util';
import { createVue, destroyVM, triggerKeyDown } from '../util';
describe('Tabs', () => {
let vm;
@@ -570,4 +570,40 @@ describe('Tabs', () => {
});
}, 100);
});
it('keyboard event', done => {
vm = createVue({
template: `
<el-tabs v-model="activeName">
<el-tab-pane label="用户管理" name="first">A</el-tab-pane>
<el-tab-pane label="配置管理" name="second">B</el-tab-pane>
<el-tab-pane label="角色管理" name="third">C</el-tab-pane>
<el-tab-pane label="定时任务补偿" name="fourth">D</el-tab-pane>
</el-tabs>
`,
data() {
return {
activeName: 'second'
};
}
}, true);
expect(vm.activeName).to.be.equal('second');
vm.$nextTick(() => {
triggerKeyDown(vm.$el.querySelector('#tab-second'), 39);
expect(vm.activeName).to.be.equal('third');
triggerKeyDown(vm.$el.querySelector('#tab-third'), 39);
expect(vm.activeName).to.be.equal('fourth');
triggerKeyDown(vm.$el.querySelector('#tab-fourth'), 39);
expect(vm.activeName).to.be.equal('first');
triggerKeyDown(vm.$el.querySelector('#tab-first'), 37);
expect(vm.activeName).to.be.equal('fourth');
triggerKeyDown(vm.$el.querySelector('#tab-fourth'), 37);
expect(vm.activeName).to.be.equal('third');
done();
});
});
});

2
types/loading.d.ts vendored
View File

@@ -50,6 +50,8 @@ export interface ElLoading {
/** If you do not have a specific DOM node to attach the Loading directive, or if you simply prefer not to use Loading as a directive, you can call this service with some configs to open a Loading instance. */
service (options: LoadingServiceOptions): ElLoadingComponent
directive: object
}
declare module 'vue/types/vue' {

2
types/tabs.d.ts vendored
View File

@@ -27,5 +27,5 @@ export declare class ElTabs extends ElementUIComponent {
stretch: Boolean
/** Hook function before switching tab. If false or a Promise is returned and then is rejected, switching will be prevented */
beforeLeave: () => boolean | Promise<any>
beforeLeave: (activeName: string, oldActiveName: string) => boolean | Promise<any>
}