Popper: Fixing getPosition comments;

pull/2419/head
Liril 2017-01-15 20:18:53 +08:00
commit 796185b56a
131 changed files with 2207 additions and 1270 deletions

View File

@ -1,5 +1,19 @@
## Changelog
### 1.1.3
*2017-01-09*
- Fixed DatePicker not firing change event when cleared for the first time upon page load, #2167
- Fixed DatePicker year calculating error when choosing the next year, #2152
- Added `default-sort-prop` and `default-sort-order` attributes for Table, #2182 (by @njleonzhang)
- Fixed filterable Select filtering other options with initial value, #2196
- Added custom i18n processing, making Element compatible with i18n plugins other than `vue-i18n`, #2129
- Added `resize` attribute for Input, #2263 (by @Kingwl)
- Fixed Autocomplete not hiding dropdown when blurred, #2247
- Fixed style issues with nested Tabs, #2212 (by @Kingwl)
- Fixed Tabs' tab bar locating error when non-first item is initially activated, #2192
### 1.1.2
*2016-12-30*

View File

@ -1,5 +1,18 @@
## 更新日志
### 1.1.3
*2017-01-09*
- 修复 DatePicker 页面加载后首次清空不会触发 `change` 事件,#2167
- 修复 DatePicker 选择下一年时,年份计算错误,#2152
- 新增 Table 的 `default-sort-prop``default-sort-order` 属性,#2182by @njleonzhang
- 修复有默认值的可搜索 Select 其他数据被过滤的问题,#2196
- 新增自定义 i18n 处理方法,方便和除了 `vue-i18n` 之外的插件使用,#2129
- 新增 Input `resize` 属性,#2263by @Kingwl
- 修复 Autocomplete 在 blur 事件触发时没有隐藏下拉列表的问题,#2247
- 修复 Tabs 嵌套使用时的样式问题,#2212by @Kingwl
- 修复 Tabs 默认激活非第一项时 tabBar 的显示位置不正确的问题,#2192
### 1.1.2
*2016-12-30*

View File

@ -15,6 +15,14 @@
> A Vue.js 2.0 UI Toolkit for Web.
<p align="center">
<b>Special thanks to the generous sponsorship by:</b>
<br><br>
<a href="https://laravist.com">
<img width="300px" src="https://fuss10.elemecdn.com/4/87/c072c1651b0efd1c5cde39bc8b422png.png">
</a>
</p>
## Links
- [Home Page](http://element.eleme.io/)
- [Docs](http://element.eleme.io/#/component)

View File

@ -6,18 +6,25 @@ var path = require('path');
var OUTPUT_PATH = path.join(__dirname, '../../src/index.js');
var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}\';';
var INSTALL_COMPONENT_TEMPLATE = ' Vue.component({{name}}.name, {{name}});';
var INSTALL_COMPONENT_TEMPLATE = ' {{name}}';
var MAIN_TEMPLATE = `/* Automatic generated by './build/bin/build-entry.js' */
{{include}}
import locale from 'element-ui/src/locale';
const components = [
{{install}}
];
const install = function(Vue, opts = {}) {
/* istanbul ignore if */
if (install.installed) return;
locale.use(opts.locale);
locale.i18n(opts.i18n);
{{install}}
components.map(component => {
Vue.component(component.name, component);
});
Vue.use(Loading.directive);
@ -38,6 +45,7 @@ if (typeof window !== 'undefined' && window.Vue) {
module.exports = {
version: '{{version}}',
locale: locale.use,
i18n: locale.i18n,
install,
Loading,
{{list}}
@ -72,7 +80,7 @@ ComponentNames.forEach(name => {
var template = render(MAIN_TEMPLATE, {
include: includeComponentTemplate.join('\n'),
install: installTemplate.join('\n'),
install: installTemplate.join(',\n'),
version: process.env.VERSION || require('../../package.json').version,
list: listTemplate.join(',\n')
});

View File

@ -6,6 +6,7 @@ var saladConfig = require('../packages/theme-default/salad.config.json');
var utilsList = fs.readdirSync(path.resolve(__dirname, '../src/utils'));
var mixinsList = fs.readdirSync(path.resolve(__dirname, '../src/mixins'));
var transitionList = fs.readdirSync(path.resolve(__dirname, '../src/transitions'));
var externals = {};
Object.keys(Components).forEach(function(key) {
@ -21,6 +22,10 @@ mixinsList.forEach(function(file) {
file = path.basename(file, '.js');
externals[`element-ui/src/mixins/${file}`] = `element-ui/lib/mixins/${file}`;
});
transitionList.forEach(function(file) {
file = path.basename(file, '.js');
externals[`element-ui/src/transitions/${file}`] = `element-ui/lib/transitions/${file}`;
});
externals = [Object.assign({
vue: 'vue'

View File

@ -1,7 +1,6 @@
<style lang="css">
@import 'highlight.js/styles/color-brewer.css';
@import 'assets/styles/common.css';
@import 'assets/styles/fonts/style.css';
html, body {
margin: 0;

View File

@ -818,6 +818,7 @@ Form component allows you to verify your data, helping you find and correct erro
| label-position | position of label | string | left/right/top | right |
| label-width | width of label, and all form items will inherit from `Form` | string | — | — |
| label-suffix | suffix of the label | string | — | — |
| show-message | whether to show the error message | boolean | — | true |
### Form Methods
@ -837,3 +838,4 @@ Form component allows you to verify your data, helping you find and correct erro
| required | whether the field is required or not, will be determined by validation rules if omitted | string | — | false |
| rules | validation rules of form | object | — | — |
| error | field error message, set its value and the field will validate error and show this message immediately | string | — | — |
| show-message | whether to show the error message | boolean | — | true |

View File

@ -56,6 +56,21 @@ Vue.locale('zh-cn', zhLocale)
Vue.locale('en', enLocale)
```
## Compatibility with other i18n plugins
Element may not be compatible with i18n plugins other than vue-i18n, but you can customize how Element processes i18n.
```javascript
import Vue from 'vue'
import Element from 'element-ui'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
Vue.use(Element, {
i18n: function (path, options) {
// ...
}
})
```
Currently Element ships with the following languages:
<ul class="language-list">
@ -79,6 +94,7 @@ Currently Element ships with the following languages:
<li>Farsi (fa)</li>
<li>Thai (th)</li>
<li>Indonesian (id)</li>
<li>Bulgarian (bg)</li>
</ul>
If your target language is not included, you are more than welcome to contribute: just add another language config [here](https://github.com/ElemeFE/element/tree/master/src/locale/lang) and create a pull request.

View File

@ -28,6 +28,8 @@
input8: '',
input9: '',
textarea: '',
textarea2: '',
textarea3: '',
select: '',
state1: '',
state2: '',
@ -218,14 +220,14 @@ export default {
### Textarea
Resizable for entering multiple lines of text information.
Resizable for entering multiple lines of text information. Add attribute `type="textarea"` to change `input` into native `textarea`.
::: demo Add attribute `type="textarea"` to change `input` into native `textarea`.
::: demo Control the height by setting the `rows` prop.
```html
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:rows="2"
placeholder="Please input"
v-model="textarea">
</el-input>
@ -242,6 +244,40 @@ export default {
```
:::
### Autosize Textarea
Setting the `autosize` prop for a textarea type of Input makes the height to automatically adjust based on the content. An options object can be provided to `autosize` to specify the minimum and maximum number of lines the textarea can automatically adjust.
::: demo
```html
<el-input
type="textarea"
autosize
placeholder="Please input"
v-model="textarea2">
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="Please input"
v-model="textarea3">
</el-input>
<script>
export default {
data() {
return {
textarea2: '',
textarea3: ''
}
}
}
</script>
```
:::
### Mixed input
Prepend or append an element, generally a label or a button.
@ -269,7 +305,11 @@ Prepend or append an element, generally a label or a button.
<el-button slot="append" icon="search"></el-button>
</el-input>
</div>
<style>
.el-select .el-input {
width: 110px;
}
</style>
<script>
export default {
data() {
@ -565,6 +605,7 @@ Search data from server-side.
|name | same as `name` in native input | string | — | — |
|max | same as `max` in native input | * | — | — |
|min | same as `min` in native input | * | — | — |
|resize| control the resizability | string | none, both, horizontal, vertical | — |
|autofocus | same as `autofocus` in native input | boolean | — | false |
|form | same as `form` in native input | string | — | — |
@ -588,6 +629,7 @@ Attribute | Description | Type | Options | Default
|custom-item | component name of your customized suggestion list item | string | — | — |
|fetch-suggestions | a method to fetch input suggestions. When suggestions are ready, invoke `callback(data:[])` to return them to Autocomplete | Function(queryString, callback) | — | — |
| popper-class | custom class name for autocomplete's dropdown | string | — | — |
| trigger-on-focus | whether show suggestions when input focus | boolean | — | true |
### Autocomplete Events

View File

@ -32,7 +32,7 @@ Top bar NavMenu can be used in a variety of scenarios.
<el-menu-item index="2-2">item two</el-menu-item>
<el-menu-item index="2-3">item three</el-menu-item>
</el-submenu>
<el-menu-item index="3">Orders</el-menu-item>
<el-menu-item index="3"><a href="https://www.ele.me" target="_blank">Orders</a></el-menu-item>
</el-menu>
<div class="line"></div>
<el-menu default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect">
@ -43,7 +43,7 @@ Top bar NavMenu can be used in a variety of scenarios.
<el-menu-item index="2-2">item two</el-menu-item>
<el-menu-item index="2-3">item three</el-menu-item>
</el-submenu>
<el-menu-item index="3">Orders </el-menu-item>
<el-menu-item index="3"><a href="https://www.ele.me" target="_blank">Orders</a></el-menu-item>
</el-menu>
<script>

View File

@ -64,7 +64,21 @@
message: 'This is a message',
showCancelButton: true,
confirmButtonText: 'OK',
cancelButtonText: 'Cancel'
cancelButtonText: 'Cancel',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = 'Loading...';
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 3000);
} else {
done();
}
}
}).then(action => {
setTimeout(() => {
this.$message({
@ -194,7 +208,7 @@ Prompt is used when user input is required.
Can be customized to show various content.
:::demo The three methods mentioned above are repackagings of the `$msgbox` method. This example calls `$msgbox` method directly using the `showCancelButton` attribute, which is used to indicate if a cancel button is displayed. Besides we can use `cancelButtonClass` to add a custom style and `cancelButtonText` to customize the button text. The confirm button also has these fields. A complete list of fields can be found at the end of this documentation.
:::demo The three methods mentioned above are repackagings of the `$msgbox` method. This example calls `$msgbox` method directly using the `showCancelButton` attribute, which is used to indicate if a cancel button is displayed. Besides we can use `cancelButtonClass` to add a custom style and `cancelButtonText` to customize the button text (the confirm button also has these fields, and a complete list of fields can be found at the end of this documentation). This example also uses the `beforeClose` attribute. It is a method and will be triggered when the MessageBox instance will be closed, and its execution will stop the instance from closing. It has three parameters: `action`, `instance` and `done`. Using it enables you to manipulate the instance before it closes, e.g. activating `loading` for confirm button; you can invoke the `done` method to close the MessageBox instance (if `done` is not called inside `beforeClose`, the instance will not be closed).
```html
<template>
@ -210,7 +224,21 @@ Can be customized to show various content.
message: 'This is a message',
showCancelButton: true,
confirmButtonText: 'OK',
cancelButtonText: 'Cancel'
cancelButtonText: 'Cancel',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = 'Loading...';
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 3000);
} else {
done();
}
}
}).then(action => {
this.$message({
type: 'info',
@ -246,7 +274,8 @@ The corresponding methods are: `MessageBox`, `MessageBox.alert`, `MessageBox.con
| message | content of the MessageBox | string | — | — |
| type | message type, used for icon display | string | success/info/warning/error | — |
| customClass | custom class name for MessageBox | string | — | — |
| callback | MessageBox closing callback if you don't prefer Promise | function(action), where action can be 'confirm' or 'cancel' | — | — |
| callback | MessageBox closing callback if you don't prefer Promise | function(action), where action can be 'confirm' or 'cancel', and `instance` is the MessageBox instance. You can access to that instance's attributes and methods | — | — |
| beforeClose | callback before MessageBox closes, and it will prevent MessageBox from closing | function(action, instance, done), where `action` can be 'confirm' or 'cancel'; `instance` is the MessageBox instance, and you can access to that instance's attributes and methods; `done` is for closing the instance | — | — |
| lockScroll | whether to lock body scroll when MessageBox prompts | boolean | — | true |
| showCancelButton | whether to show a cancel button | boolean | — | false (true when called with confirm and prompt) |
| showConfirmButton | whether to show a confirm button | boolean | — | true |

View File

@ -2,9 +2,11 @@
module.exports = {
methods: {
open() {
const h = this.$createElement;
this.$notify({
title: 'Title',
message: 'This is a reminder'
message: h('p', { style: 'color: red' }, 'This is a reminder')
});
},
@ -61,14 +63,14 @@
};
</script>
## Notification
## Notification
Displays a global notification message at the upper right corner of the page.
### Basic usage
::: demo Element has registered the `$notify` method and it receives an object as its parameter. In the simplest case, you can set the `title` field and the` message` field for the title and body of the notification. By default, the notification automatically closes after 4500ms, but by setting `duration` you can control its duration. Specifically, if set to `0`, it will not close automatically. Note that `duration` receives a `Number` in milliseconds.
```html
<template>
<el-button
@ -87,9 +89,11 @@ Displays a global notification message at the upper right corner of the page.
export default {
methods: {
open() {
const h = this.$createElement;
this.$notify({
title: 'Title',
message: 'This is a reminder'
message: h('p', { style: 'color: red' }, 'This is a reminder')
});
},
@ -201,6 +205,7 @@ Customize Notification's offset from the top edge of the screen
}
</script>
```
:::
### Global method
@ -220,7 +225,7 @@ In this case you should call `Notification(options)`. We have also registered me
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| title | title | string | — | — |
| message | description text | string | — | — |
| message | description text | string/Vue.VNode | — | — |
| type | notification type | string | success/warning/info/error | — |
| iconClass | custom icon's class. It will be overridden by `type` | string | — | — |
| customClass | custom class name for Notification | string | — | — |

View File

@ -212,6 +212,7 @@ Of course, you can nest other operations. It's more light-weight than using a di
| content | popover content, can be replaced with a default `slot` | string | — | — |
| width | popover width | string, number | — | Min width 150px |
| placement | popover placement | string | top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end | bottom |
| disabled | whether Popover is disabled | boolean | — | false |
| value(v-model) | whether popover is visible | Boolean | — | false |
| offset | popover offset | number | — | 0 |
| transition | popover transition animation | string | — | fade-in-linear |

View File

@ -127,6 +127,7 @@ Set value via a input box.
| disabled | whether Slider is disabled | boolean | — | false |
| step | step size | number | — | 1 |
| show-input | whether to display an input box | boolean | — | false |
| show-input-controls | whether to display control buttons when `show-input` is true | boolean | — | true |
| show-stops | whether to display breakpoints | boolean | — | false |
## Events

View File

@ -120,6 +120,7 @@ Vertical step bars.
| process-status | status of current step | string | wait/process/finish/error/success | process |
| finish-status | status of end step | string | wait/process/finish/error/success | finish |
| align-center | whether step description is centered | boolean | — | false |
| center | center whole `Steps` component | boolean | - | false |
### Step Attributes
| Attribute | Description | Type | Accepted Values | Default |

View File

@ -1122,13 +1122,15 @@ You can also select multiple rows.
Sort the data to find or compare data quickly.
:::demo Set attribute `sortable` in a certain column to sort the data based on this column. It accepts `Boolean` with a default value `false`. In this example we use another attribute named `formatter` to format the value of certain columns. It accepts a function which has two parameters: `row` and `column`. You can handle it according to your own needs.
:::demo Set table attribute `default-sort-prop` and `default-sort-order` to determine default sort column and order. Set attribute `sortable` in a certain column to sort the data based on this column. It accepts `Boolean` with a default value `false`. In this example we use another attribute named `formatter` to format the value of certain columns. It accepts a function which has two parameters: `row` and `column`. You can handle it according to your own needs.
```html
<template>
<el-table
:data="tableData"
border
style="width: 100%">
style="width: 100%"
default-sort-prop="date"
default-sort-order="descending">
<el-table-column
prop="date"
label="Date"
@ -1453,6 +1455,8 @@ When the row content is too long and you do not want to display the horizontal s
| empty-text | Displayed text when data is empty. You can customize this area with `slot="empty"` | String | — | No Data |
| default-expand-all | whether expand all rows by default, only works when the table has a column type="expand" | Boolean | — | false |
| expand-row-keys | set expanded rows by this prop, prop's value is the keys of expand rows, you should set row-key before using this prop | Array | — | |
| default-sort-prop | set the `prop` of default sort column. | String | - | - |
| default-sort-order | set the default sort order. You should set `default-sort-prop` before using this prop. | String | ascending, descending | ascending |
### Table Events
| Event Name | Description | Parameters |

View File

@ -113,12 +113,12 @@ Tooltip has 9 placements.
.item {
margin: 4px;
}
.left .el-tooltip__popper,
.right .el-tooltip__popper {
padding: 8px 10px;
}
.el-button {
width: 110px;
}
@ -145,7 +145,7 @@ Tooltip has two themes: `dark` and `light`。
### More Content
Display multiple lines of text and set their format.
Display multiple lines of text and set their format.
:::demo Override attribute `content` of `el-tooltip` by adding a slot named `content`.
```html
@ -170,7 +170,7 @@ In fact, Tooltip is an extension based on [Vue-popper](https://github.com/elemen
```html
<template>
<el-tooltip :disabled="disabled" content="click to close tooltip function" placement="bottom" effect="light">
<el-button @click="disabled=true">click to close tooltip function</el-button>
<el-button @click="disabled = !disabled">click to {{disabled ? 'active' : 'close'}} tooltip function</el-button>
</el-tooltip>
</template>

View File

@ -803,6 +803,7 @@
| label-position | 表单域标签的位置 | string | right/left/top | right |
| label-width | 表单域标签的宽度,所有的 form-item 都会继承 form 组件的 labelWidth 的值 | string | — | — |
| label-suffix | 表单域标签的后缀 | string | — | — |
| show-message | 是否显示校验错误信息 | boolean | — | true |
### Form Methods
@ -822,3 +823,4 @@
| required | 是否必填,如不设置,则会根据校验规则自动生成 | bolean | — | false |
| rules | 表单验证规则 | object | — | — |
| error | 表单域验证错误信息, 设置该值会使表单验证状态变为`error`,并显示该错误信息 | string | — | — |
| show-message | 是否显示校验错误信息 | boolean | — | true |

View File

@ -68,6 +68,22 @@ Vue.locale('zh-cn', zhLocale)
Vue.locale('en', enLocale)
```
## 兼容其他 i18n 插件
如果不使用 `vue-i18n`,而是用其他的 i18n 插件Element 将无法兼容,但是可以自定义 Element 的 i18n 的处理方法。
```javascript
import Vue from 'vue'
import Element from 'element-ui'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
Vue.use(Element, {
i18n: function (path, options) {
// ...
}
})
```
目前 Element 内置了以下语言:
<ul class="language-list">
<li>简体中文zh-CN</li>
@ -90,6 +106,7 @@ Vue.locale('en', enLocale)
<li>波斯语fa</li>
<li>泰语th</li>
<li>印尼语id</li>
<li>保加利亚语bg</li>
</ul>
如果你需要使用其他的语言,欢迎贡献 PR只需在 [这里](https://github.com/ElemeFE/element/tree/master/src/locale/lang) 添加一个语言配置文件即可。

View File

@ -28,6 +28,8 @@
input8: '',
input9: '',
textarea: '',
textarea2: '',
textarea3: '',
select: '',
state1: '',
state2: '',
@ -257,13 +259,13 @@ export default {
### 文本域
可调整大小,用于输入多行文本信息
用于输入多行文本信息,通过将 `type` 属性的值指定为 textarea。
::: demo 通过将 `type` 属性的值指定为 textarea。
::: demo 文本域高度可通过 `rows` 属性控制
```html
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:rows="2"
placeholder="请输入内容"
v-model="textarea">
</el-input>
@ -280,6 +282,39 @@ export default {
```
:::
### 可自适应文本高度的文本域
通过设置 `autosize` 属性可以使得文本域的高度能够根据文本内容自动进行调整,并且 `autosize` 还可以设定为一个对象,指定最小行数和最大行数。
::: demo
```html
<el-input
type="textarea"
autosize
placeholder="请输入内容"
v-model="textarea2">
</el-input>
<div style="margin: 20px 0;"></div>
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="textarea3">
</el-input>
<script>
export default {
data() {
return {
textarea2: '',
textarea3: ''
}
}
}
</script>
```
:::
### 复合型输入框
可前置或后置元素,一般为标签或按钮
@ -306,6 +341,11 @@ export default {
<el-button slot="append" icon="search"></el-button>
</el-input>
</div>
<style>
.el-select .el-input {
width: 110px;
}
</style>
<script>
export default {
data() {
@ -728,6 +768,7 @@ export default {
| name | 原生属性 | string | — | — |
| max | 原生属性,设置最大值 | * | — | — |
| min | 原生属性,设置最小值 | * | — | — |
| resize | 控制是否能被用户缩放 | string | none, both, horizontal, vertical | — |
| autofocus | 原生属性,自动获取焦点 | boolean | true, false | false |
| form | 原生属性 | string | — | — |
@ -749,6 +790,7 @@ export default {
| custom-item | 通过该参数指定自定义的输入建议列表项的组件名 | string | — | — |
| fetch-suggestions | 返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它 | Function(queryString, callback) | — | — |
| popper-class | Autocomplete 下拉列表的类名 | string | — | — |
| trigger-on-focus | 是否在输入框 focus 时显示建议列表 | boolean | — | true |
### Autocomplete Events
| 事件名称 | 说明 | 回调参数 |

View File

@ -53,6 +53,7 @@
适用广泛的基础用法。
::: demo 导航菜单默认为垂直模式,通过 `mode` 属性可以使导航菜单变更为水平模式。另外,在菜单中通过 `submenu` 组件可以生成二级菜单。
```html
<el-menu theme="dark" default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">处理中心</el-menu-item>
@ -62,7 +63,7 @@
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
</el-submenu>
<el-menu-item index="3">订单管理</el-menu-item>
<el-menu-item index="3"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
</el-menu>
<div class="line"></div>
<el-menu default-active="1" class="el-menu-demo" mode="horizontal" @select="handleSelect">
@ -73,7 +74,7 @@
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
</el-submenu>
<el-menu-item index="3">订单管理</el-menu-item>
<el-menu-item index="3"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
</el-menu>
<script>

View File

@ -65,7 +65,21 @@
message: '这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容',
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消'
cancelButtonText: '取消',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = '执行中...';
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 3000);
} else {
done();
}
}
}).then(action => {
setTimeout(() => {
this.$message({
@ -191,7 +205,7 @@
可自定义配置不同内容。
:::demo 以上三个方法都是对`$msgbox`方法的再包装。本例直接调用`$msgbox`方法,使用了`showCancelButton`字段,用于显示取消按钮。另外可使用`cancelButtonClass`为其添加自定义样式,使用`cancelButtonText`来自定义按钮文本Confirm 按钮也具有相同的字段,在文末的字段说明中有完整的字段列表。
:::demo 以上三个方法都是对`$msgbox`方法的再包装。本例直接调用`$msgbox`方法,使用了`showCancelButton`字段,用于显示取消按钮。另外可使用`cancelButtonClass`为其添加自定义样式,使用`cancelButtonText`来自定义按钮文本Confirm 按钮也具有相同的字段,在文末的字段说明中有完整的字段列表)。此例还使用了`beforeClose`属性,它的值是一个方法,会在 MessageBox 的实例关闭前被调用,同时暂停实例的关闭。它有三个参数:`action`、实例本身和`done`方法。使用它能够在关闭前对实例进行一些操作,比如为确定按钮添加`loading`状态等;此时若需要关闭实例,可以调用`done`方法(若在`beforeClose`中没有调用`done`,则实例不会关闭)
```html
<template>
@ -207,7 +221,21 @@
message: '这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容, 这是一段内容',
showCancelButton: true,
confirmButtonText: '确定',
cancelButtonText: '取消'
cancelButtonText: '取消',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true;
instance.confirmButtonText = '执行中...';
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 3000);
} else {
done();
}
}
}).then(action => {
this.$message({
type: 'info',
@ -243,7 +271,8 @@ import { MessageBox } from 'element-ui';
| message | MessageBox 消息正文内容 | string | — | — |
| type | 消息类型,用于显示图标 | string | success/info/warning/error | — |
| customClass | MessageBox 的自定义类名 | string | — | — |
| callback | 若不使用 Promise可以使用此参数指定 MessageBox 关闭后的回调 | function(action)action 的值为'confirm'或'cancel' | — | — |
| callback | 若不使用 Promise可以使用此参数指定 MessageBox 关闭后的回调 | function(action, instance)action 的值为'confirm'或'cancel', instance 为 MessageBox 实例,可以通过它访问实例上的属性和方法 | — | — |
| beforeClose | MessageBox 关闭前的回调,会暂停实例的关闭 | function(action, instance, done)action 的值为'confirm'或'cancel'instance 为 MessageBox 实例可以通过它访问实例上的属性和方法done 用于关闭 MessageBox 实例 | — | — |
| lockScroll | 是否在 MessageBox 出现时将 body 滚动锁定 | boolean | — | true |
| showCancelButton | 是否显示取消按钮 | boolean | — | false以 confirm 和 prompt 方式调用时为 true |
| showConfirmButton | 是否显示确定按钮 | boolean | — | true |

View File

@ -2,9 +2,11 @@
module.exports = {
methods: {
open() {
const h = this.$createElement;
this.$notify({
title: '标题名称',
message: '这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案'
message: h('p', { style: 'color: red'}, '这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案')
});
},
@ -45,7 +47,7 @@
message: '这是一条错误的提示消息'
});
},
open7() {
this.$notify.success({
title: '成功',
@ -88,9 +90,11 @@
export default {
methods: {
open() {
const h = this.$createElement;
this.$notify({
title: '标题名称',
message: '这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案'
message: h('p', { style: 'color: red'}, '这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案')
});
},
@ -222,7 +226,7 @@ import { Notification } from 'element-ui';
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| title | 标题 | string | — | — |
| message | 说明文字 | string | — | — |
| message | 说明文字 | string/Vue.VNode | — | — |
| type | 主题样式,如果不在可选值内将被忽略 | string | success/warning/info/error | — |
| iconClass | 自定义图标的类名。若设置了 `type`,则 `iconClass` 会被覆盖 | string | — | — |
| customClass | 自定义类名 | string | — | — |

View File

@ -239,6 +239,7 @@ Popover 的属性与 Tooltip 很类似,它们都是基于`Vue-popper`开发的
| content | 显示的内容,也可以通过 `slot` 传入 DOM | String | — | — |
| width | 宽度 | String, Number | — | 最小宽度 150px |
| placement | 出现位置 | String | top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end | bottom |
| disabled | Popover 是否可用 | Boolean | — | false |
| value(v-model) | 状态是否可见 | Boolean | — | false |
| offset | 出现位置的偏移量 | Number | — | 0 |
| transition | 定义渐变动画 | String | — | fade-in-linear |

View File

@ -151,6 +151,7 @@
| disabled | 是否禁用 | boolean | — | false |
| step | 步长 | number | — | 1 |
| show-input | 是否显示输入框 | boolean | — | false |
| show-input-controls | 在显示输入框的情况下,是否显示输入框的控制按钮 | boolean | — | true|
| show-stops | 是否显示间断点 | boolean | — | false |
### Events

View File

@ -113,7 +113,8 @@
| active | 设置当前激活步骤 | number | — | 0 |
| process-status | 设置当前步骤的状态 | string | wait/process/finish/error/success | process |
| finish-status | 设置结束步骤的状态 | string | wait/process/finish/error/success | finish |
| align-center | 标题描述居中对齐 | boolean | false, true | false |
| align-center | 标题描述居中对齐 | boolean | - | false |
| center | 组件居中显示 | boolean | - | false |
### Step Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -1139,13 +1139,16 @@
对表格进行排序,可快速查找或对比数据。
:::demo 在列中设置`sortable`属性即可实现以该列为基准的排序,接受一个`Boolean`,默认为`false`。在本例中,我们还使用了`formatter`属性,它用于格式化指定列的值,接受一个`Function`,会传入两个参数:`row`和`column`,可以根据自己的需求进行处理。
:::demo 可以通过表的`default-sort-prop`和`default-sort-order`属性设置默认的排序列和排序顺序。在列中设置`sortable`属性即可实现以该列为基准的排序,接受一个`Boolean`,默认为`false`。在本例中,我们还使用了`formatter`属性,它用于格式化指定列的值,接受一个`Function`,会传入两个参数:`row`和`column`,可以根据自己的需求进行处理。
```html
<template>
<el-table
:data="tableData"
border
style="width: 100%">
style="width: 100%"
default-sort-prop="date"
default-sort-order="descending"
>
<el-table-column
prop="date"
label="日期"
@ -1475,6 +1478,8 @@
| empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | — | 暂无数据 |
| default-expand-all | 是否默认展开所有行,当 Table 中存在 type="expand" 的 Column 的时候有效 | Boolean | — | false |
| expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。| Array | — | |
| default-sort-prop | 默认的排序列的prop。| String | - | - |
| default-sort-order | 设置默认的排序顺序。需要设置`default-sort-prop`才能使用。 | String | ascending, descending | ascending |
### Table Events
@ -1525,4 +1530,4 @@
| filters | 数据过滤的选项,数组格式,数组中的元素需要有 text 和 value 属性。 | Array[{ text, value }] | — | — |
| filter-multiple | 数据过滤的选项是否多选 | Boolean | — | true |
| filter-method | 数据过滤使用的方法,如果是多选的筛选项,对每一条数据会执行多次,任意一次返回 true 就会显示。 | Function(value, row) | — | — |
| filtered-value | 选中的数据过滤项,如果需要自定义表头过滤的渲染方式,可能会需要此属性。 | Array | — | — |
| filtered-value | 选中的数据过滤项,如果需要自定义表头过滤的渲染方式,可能会需要此属性。 | Array | — | — |

View File

@ -2,7 +2,7 @@
export default {
data() {
return {
activeName: 'first',
activeName: 'second',
activeName2: 'first',
tabs: [{
title: 'Tab 1',
@ -50,7 +50,7 @@
export default {
data() {
return {
activeName: 'first'
activeName: 'second'
};
},
methods: {

View File

@ -134,7 +134,7 @@
.item {
margin: 4px;
}
.left .el-tooltip__popper,
.right .el-tooltip__popper {
padding: 8px 10px;
@ -189,7 +189,7 @@ Tooltip 组件提供了两个不同的主题:`dark`和`light`。
```html
<template>
<el-tooltip :disabled="disabled" content="点击关闭 tooltip 功能" placement="bottom" effect="light">
<el-button @click="disabled = true">点击关闭 tooltip 功能</el-button>
<el-button @click="disabled = !disabled">点击{{disabled ? '开启' : '关闭'}} tooltip 功能</el-button>
</el-tooltip>
</template>
```

View File

@ -159,6 +159,7 @@
}
}
fragments = fragments.replace(/#(\d+)/g, '<a href="https://github.com/ElemeFE/element/issues/$1" target="_blank">#$1</a>');
fragments = fragments.replace(/@(\w+)/g, '<a href="https://github.com/$1" target="_blank">@$1</a>');
this.$refs.timeline.innerHTML = `${fragments}</li>`;
changeLog.$el.remove();

View File

@ -1,4 +1,4 @@
{
"1.0.9": "1.0",
"1.1.2": "1.1"
"1.1.3": "1.1"
}

View File

@ -1,6 +1,6 @@
{
"name": "element-ui",
"version": "1.1.2",
"version": "1.1.3",
"description": "A Component Library for Vue.js.",
"main": "lib/element-ui.common.js",
"files": [
@ -103,7 +103,7 @@
"phantomjs-prebuilt": "^2.1.13",
"postcss": "^5.1.2",
"postcss-loader": "^0.11.1",
"postcss-salad": "^1.0.5",
"postcss-salad": "^1.0.8",
"rimraf": "^2.5.4",
"sinon": "^1.17.6",
"sinon-chai": "^2.8.0",

View File

@ -11,14 +11,14 @@
<li
v-if="!parent.customItem"
:class="{'highlighted': parent.highlightedIndex === index}"
@click="parent.select(index)"
@click="select(item)"
>
{{item.value}}
</li>
<component
v-else
:class="{'highlighted': parent.highlightedIndex === index}"
@click="parent.select(index)"
@click="select(item)"
:is="parent.customItem"
:item="item"
:index="index">
@ -29,8 +29,9 @@
</template>
<script>
import Popper from 'element-ui/src/utils/vue-popper';
import Emitter from 'element-ui/src/mixins/emitter';
export default {
mixins: [Popper],
mixins: [Popper, Emitter],
componentName: 'ElAutocompleteSuggestions',
@ -53,6 +54,12 @@
}
},
methods: {
select(item) {
this.dispatch('ElAutocomplete', 'item-click', item);
}
},
mounted() {
this.popperElm = this.$el;
this.referenceElm = this.$parent.$refs.input.$refs.input;

View File

@ -1,5 +1,5 @@
<template>
<div class="el-autocomplete" v-clickoutside="handleBlur">
<div class="el-autocomplete" v-clickoutside="handleClickoutside">
<el-input
ref="input"
:value="value"
@ -9,9 +9,10 @@
:size="size"
@change="handleChange"
@focus="handleFocus"
@blur="handleBlur"
@keydown.up.native="highlight(highlightedIndex - 1)"
@keydown.down.native="highlight(highlightedIndex + 1)"
@keydown.enter.stop.native="select(highlightedIndex)"
@keydown.enter.stop.native="handleKeyEnter"
>
<template slot="prepend" v-if="$slots.prepend">
<slot name="prepend"></slot>
@ -39,6 +40,8 @@
mixins: [Emitter],
componentName: 'ElAutocomplete',
components: {
ElInput,
ElAutocompleteSuggestions
@ -53,6 +56,7 @@
name: String,
size: String,
value: String,
autofocus: Boolean,
fetchSuggestions: Function,
triggerOnFocus: {
type: Boolean,
@ -62,53 +66,65 @@
},
data() {
return {
isFocus: false,
suggestions: [],
suggestionVisible: false,
loading: false,
highlightedIndex: -1
};
},
computed: {
suggestionVisible() {
const suggestions = this.suggestions;
let isValidData = Array.isArray(suggestions) && suggestions.length > 0;
return (isValidData || this.loading) && this.isFocus;
}
},
watch: {
suggestionVisible(val) {
this.broadcast('ElAutocompleteSuggestions', 'visible', [val, this.$refs.input.$refs.input.offsetWidth]);
}
},
methods: {
getData(queryString) {
this.loading = true;
this.fetchSuggestions(queryString, (suggestions) => {
this.loading = false;
if (Array.isArray(suggestions)) {
this.suggestions = suggestions;
} else {
console.error('autocomplete suggestions must be an array');
}
});
},
handleChange(value) {
this.$emit('input', value);
this.showSuggestions(value);
this.getData(value);
},
handleFocus() {
this.isFocus = true;
if (this.triggerOnFocus) {
this.showSuggestions(this.value);
this.getData(this.value);
}
},
handleBlur() {
this.hideSuggestions();
// blur select
setTimeout(_ => {
this.isFocus = false;
}, 100);
},
select(index) {
if (this.suggestions && this.suggestions[index]) {
this.$emit('input', this.suggestions[index].value);
this.$emit('select', this.suggestions[index]);
this.$nextTick(() => {
this.hideSuggestions();
});
handleKeyEnter() {
if (this.suggestionVisible) {
this.select(this.suggestions[this.highlightedIndex]);
}
},
hideSuggestions() {
this.suggestionVisible = false;
this.loading = false;
handleClickoutside() {
this.isFocus = false;
},
showSuggestions(value) {
this.suggestionVisible = true;
this.loading = true;
this.fetchSuggestions(value, (suggestions) => {
this.loading = false;
if (Array.isArray(suggestions) && suggestions.length > 0) {
this.suggestions = suggestions;
} else {
this.hideSuggestions();
}
select(item) {
this.$emit('input', item.value);
this.$emit('select', item);
this.$nextTick(_ => {
this.suggestions = [];
});
},
highlight(index) {
@ -134,6 +150,11 @@
this.highlightedIndex = index;
}
},
mounted() {
this.$on('item-click', item => {
this.select(item);
});
},
beforeDestroy() {
this.$refs.suggestions.$destroy();
}

View File

@ -65,7 +65,7 @@ export default {
type: String,
default: 'hover'
},
autoPlay: {
autoplay: {
type: Boolean,
default: true
},
@ -168,7 +168,7 @@ export default {
},
startTimer() {
if (this.interval <= 0 || !this.autoPlay) return;
if (this.interval <= 0 || !this.autoplay) return;
this.timer = setInterval(this.playSlides, this.interval);
},

View File

@ -4,32 +4,18 @@
<i class="el-collapse-item__header__arrow el-icon-arrow-right"></i>
<slot name="title">{{title}}</slot>
</div>
<div class="el-collapse-item__wrap" ref="contentWrap">
<div class="el-collapse-item__content" ref="content">
<slot></slot>
<collapse-transition>
<div class="el-collapse-item__wrap" v-show="isActive">
<div class="el-collapse-item__content">
<slot></slot>
</div>
</div>
</div>
</collapse-transition>
</div>
</template>
<script>
import { once } from 'element-ui/src/utils/dom';
import Emitter from 'element-ui/src/mixins/emitter';
function getTransitionendEvent(el) {
let t;
let transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
};
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
export default {
name: 'ElCollapseItem',
@ -38,6 +24,10 @@
mixins: [Emitter],
components: {
CollapseTransition
},
data() {
return {
contentWrapStyle: {
@ -66,57 +56,16 @@
watch: {
'isActive'(value) {
value ? this.open() : this.close();
}
},
methods: {
open() {
const contentWrapElm = this.$refs.contentWrap;
const contentHeight = this.contentHeight;
contentWrapElm.style.display = 'block';
contentWrapElm.style.height = '0';
setTimeout(_ => {
contentWrapElm.style.height = contentHeight + 'px';
once(contentWrapElm, getTransitionendEvent(contentWrapElm), () => {
if (!this.isActive) return;
contentWrapElm.style.height = 'auto';
});
}, 10);
},
close() {
const contentWrapElm = this.$refs.contentWrap;
const contentElm = this.$refs.content;
const contentHeight = contentElm.offsetHeight;
this.contentHeight = contentHeight;
contentWrapElm.style.height = contentHeight + 'px';
setTimeout(_ => {
contentWrapElm.style.height = '0';
once(contentWrapElm, getTransitionendEvent(contentWrapElm), () => {
if (this.isActive) return;
contentWrapElm.style.display = 'none';
});
}, 10);
},
init() {
if (!this.isActive) {
let contentWrapElm = this.$refs.contentWrap;
this.contentHeight = this.$refs.content.offsetHeight;
contentWrapElm.style.height = '0';
contentWrapElm.style.display = 'none';
}
},
handleHeaderClick() {
this.dispatch('ElCollapse', 'item-click', this);
}
},
mounted() {
this.init();
}
};
</script>

View File

@ -367,8 +367,8 @@
target = target.parentNode.cells[1];
}
let year = this.year;
let month = this.month;
let year = Number(this.year);
let month = Number(this.month);
const cellIndex = target.cellIndex;
const rowIndex = target.parentNode.rowIndex;
@ -377,7 +377,7 @@
const text = cell.text;
const className = target.className;
const newDate = new Date(this.year, this.month, 1);
const newDate = new Date(year, month, 1);
if (className.indexOf('prev') !== -1) {
if (month === 0) {

View File

@ -100,6 +100,7 @@
:range-state="rangeState"
:disabled-date="disabledDate"
@changerange="handleChangeRange"
:first-day-of-week="firstDayOfWeek"
@pick="handleRangePick">
</date-table>
</div>
@ -125,7 +126,9 @@
:range-state="rangeState"
:disabled-date="disabledDate"
@changerange="handleChangeRange"
@pick="handleRangePick"></date-table>
:first-day-of-week="firstDayOfWeek"
@pick="handleRangePick">
</date-table>
</div>
</div>
</div>
@ -232,6 +235,7 @@
value: '',
visible: '',
disabledDate: '',
firstDayOfWeek: 7,
minTimePickerVisible: false,
maxTimePickerVisible: false,
width: 0

View File

@ -436,7 +436,10 @@
const yearTranslation = this.t('el.datepicker.year');
if (this.currentView === 'year') {
const startYear = Math.floor(year / 10) * 10;
return startYear + ' ' + yearTranslation + '-' + (startYear + 9) + ' ' + yearTranslation;
if (yearTranslation) {
return startYear + ' ' + yearTranslation + ' - ' + (startYear + 9) + ' ' + yearTranslation;
}
return startYear + ' - ' + (startYear + 9);
}
return this.year + ' ' + yearTranslation;
}

View File

@ -124,7 +124,7 @@
result.push({
value: current,
disabled: compareTime(current, this.minTime || '-1:-1') <= 0 ||
compareTime(current, this.maxTime || '100:100') > 0
compareTime(current, this.maxTime || '100:100') >= 0
});
current = nextTime(current, step);
}

View File

@ -10,8 +10,8 @@
@focus="handleFocus"
@blur="handleBlur"
@keydown.native="handleKeydown"
:value="visualValue"
@change.native="visualValue = $event.target.value"
:value="displayValue"
@change.native="displayValue = $event.target.value"
ref="reference">
<i slot="icon"
class="el-input__icon"
@ -27,7 +27,7 @@
<script>
import Vue from 'vue';
import Clickoutside from 'element-ui/src/utils/clickoutside';
import { formatDate, parseDate, getWeekNumber, equalDate } from './util';
import { formatDate, parseDate, getWeekNumber, equalDate, isDate } from './util';
import Popper from 'element-ui/src/utils/vue-popper';
import Emitter from 'element-ui/src/mixins/emitter';
import ElInput from 'element-ui/packages/input';
@ -213,7 +213,7 @@ export default {
return {
pickerVisible: false,
showClose: false,
internalValue: ''
currentValue: ''
};
},
@ -222,16 +222,22 @@ export default {
if (this.readonly || this.disabled) return;
val ? this.showPicker() : this.hidePicker();
},
internalValue(val) {
if (!val && this.picker && typeof this.picker.handleClear === 'function') {
currentValue(val) {
if (val) return;
if (this.picker && typeof this.picker.handleClear === 'function') {
this.picker.handleClear();
} else {
this.$emit('input');
}
},
value: {
immediate: true,
handler(val) {
this.internalValue = val;
this.currentValue = isDate(val) ? new Date(val) : val;
}
},
displayValue(val) {
this.$emit('change', val);
}
},
@ -246,7 +252,7 @@ export default {
},
valueIsEmpty() {
const val = this.internalValue;
const val = this.currentValue;
if (Array.isArray(val)) {
for (let i = 0, len = val.length; i < len; i++) {
if (val[i]) {
@ -284,9 +290,9 @@ export default {
return HAVE_TRIGGER_TYPES.indexOf(this.type) !== -1;
},
visualValue: {
displayValue: {
get() {
const value = this.internalValue;
const value = this.currentValue;
if (!value) return;
const formatter = (
TYPE_VALUE_RESOLVER_MAP[this.type] ||
@ -318,9 +324,6 @@ export default {
},
created() {
this.cachePicker = {};
this.cacheChange = {};
// vue-popper
this.options = {
boundariesPadding: 0,
@ -340,26 +343,25 @@ export default {
handleClickIcon() {
if (this.readonly || this.disabled) return;
if (this.showClose) {
this.internalValue = '';
this.currentValue = '';
this.showClose = false;
} else {
this.pickerVisible = !this.pickerVisible;
}
},
dateIsUpdated(date, cache) {
let updated = true;
if (Array.isArray(date)) {
if (equalDate(cache.cacheDateMin, date[0]) &&
equalDate(cache.cacheDateMax, date[1])) updated = false;
cache.cacheDateMin = new Date(date[0]);
cache.cacheDateMax = new Date(date[1]);
dateChanged(dateA, dateB) {
if (Array.isArray(dateA)) {
let len = dateA.length;
if (!dateB) return true;
while (len--) {
if (!equalDate(dateA[len], dateB[len])) return true;
}
} else {
if (equalDate(cache.cacheDate, date)) updated = false;
cache.cacheDate = new Date(date);
if (!equalDate(dateA, dateB)) return true;
}
return updated;
return false;
},
handleClose() {
@ -400,7 +402,7 @@ export default {
showPicker() {
if (this.$isServer) return;
if (!this.picker) {
this.panel.defaultValue = this.internalValue;
this.panel.defaultValue = this.currentValue;
this.picker = new Vue(this.panel).$mount(document.createElement('div'));
this.picker.popperClass = this.popperClass;
this.popperElm = this.picker.$el;
@ -423,12 +425,6 @@ export default {
this.picker.selectableRange = ranges.map(range => parser(range, format));
}
if (this.type === 'time-select' && options) {
this.$watch('pickerOptions.minTime', val => {
this.picker.minTime = val;
});
}
for (const option in options) {
if (options.hasOwnProperty(option) &&
// time-picker
@ -446,9 +442,7 @@ export default {
this.picker.$on('dodestroy', this.doDestroy);
this.picker.$on('pick', (date, visible = false) => {
if (this.dateIsUpdated(date, this.cachePicker)) this.$emit('input', date);
this.$nextTick(() => this.dateIsUpdated(date, this.cacheChange) && this.$emit('change', this.visualValue));
if (this.dateChanged(date, this.value)) this.$emit('input', date);
this.pickerVisible = this.picker.visible = visible;
this.picker.resetView && this.picker.resetView();
});
@ -463,10 +457,10 @@ export default {
this.updatePopper();
if (this.internalValue instanceof Date) {
this.picker.date = new Date(this.internalValue.getTime());
if (this.currentValue instanceof Date) {
this.picker.date = new Date(this.currentValue.getTime());
} else {
this.picker.value = this.internalValue;
this.picker.value = this.currentValue;
}
this.picker.resetView && this.picker.resetView();

View File

@ -11,6 +11,12 @@ export default {
isRange: Boolean
},
data() {
return {
type: ''
};
},
created() {
this.type = this.isRange ? 'timerange' : 'time';
this.panel = this.isRange ? TimeRangePanel : TimePanel;

View File

@ -6,7 +6,7 @@ export default {
name: 'ElTimeSelect',
created() {
beforeCreate() {
this.type = 'time-select';
this.panel = Panel;
}

View File

@ -13,9 +13,13 @@ export const equalDate = function(dateA, dateB) {
};
export const toDate = function(date) {
date = new Date(date);
if (isNaN(date.getTime())) return null;
return date;
return isDate(date) ? date : null;
};
export const isDate = function(date) {
if (date === null || date === undefined) return false;
if (isNaN(new Date(date).getTime())) return false;
return true;
};
export const formatDate = function(date, format) {

View File

@ -10,7 +10,7 @@
<div class="el-form-item__content" v-bind:style="contentStyle">
<slot></slot>
<transition name="el-zoom-in-top">
<div class="el-form-item__error" v-if="validateState === 'error'">{{validateMessage}}</div>
<div class="el-form-item__error" v-if="validateState === 'error' && showMessage && form.showMessage">{{validateMessage}}</div>
</transition>
</div>
</div>
@ -58,7 +58,11 @@
required: Boolean,
rules: [Object, Array],
error: String,
validateStatus: String
validateStatus: String,
showMessage: {
type: Boolean,
default: true
}
},
watch: {
error(value) {

View File

@ -21,7 +21,11 @@
type: String,
default: ''
},
inline: Boolean
inline: Boolean,
showMessage: {
type: Boolean,
default: true
}
},
watch: {
rules() {

View File

@ -21,10 +21,11 @@
>
</span>
<el-input
v-model.number="currentValue"
:value="currentValue"
@keydown.up.native="increase"
@keydown.down.native="decrease"
@blur="handleBlur"
@input="handleInput"
:disabled="disabled"
:size="size"
:max="max"
@ -95,32 +96,20 @@
}
},
data() {
// correct the init value
let value = this.value;
if (value < this.min) {
this.$emit('input', this.min);
value = this.min;
}
if (value > this.max) {
this.$emit('input', this.max);
value = this.max;
}
return {
currentValue: value
currentValue: 0
};
},
watch: {
value(val) {
this.currentValue = val;
},
currentValue(newVal, oldVal) {
if (newVal <= this.max && newVal >= this.min) {
this.$emit('change', newVal, oldVal);
value: {
immediate: true,
handler(value) {
let newVal = Number(value);
if (isNaN(newVal)) return;
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
this.currentValue = newVal;
this.$emit('input', newVal);
} else {
this.currentValue = oldVal;
}
}
},
@ -169,17 +158,32 @@
const value = this.value || 0;
const newVal = this._increase(value, this.step);
if (newVal > this.max) return;
this.currentValue = newVal;
this.setCurrentValue(newVal);
},
decrease() {
if (this.disabled || this.minDisabled) return;
const value = this.value || 0;
const newVal = this._decrease(value, this.step);
if (newVal < this.min) return;
this.currentValue = newVal;
this.setCurrentValue(newVal);
},
handleBlur() {
this.$refs.input.setCurrentValue(this.currentValue);
},
setCurrentValue(newVal) {
const oldVal = this.currentValue;
if (newVal >= this.max) newVal = this.max;
if (newVal <= this.min) newVal = this.min;
if (oldVal === newVal) return;
this.$emit('change', newVal, oldVal);
this.$emit('input', newVal);
this.currentValue = newVal;
},
handleInput(value) {
const newVal = Number(value);
if (!isNaN(newVal)) {
this.setCurrentValue(newVal);
}
}
}
};

View File

@ -1,3 +1,5 @@
import merge from 'element-ui/src/utils/merge';
let hiddenTextarea;
const HIDDEN_STYLE = `
@ -53,7 +55,8 @@ function calculateNodeStyling(node) {
export default function calcTextareaHeight(
targetNode,
minRows = null,
maxRows = null
maxRows = null,
options = null
) {
if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea');
@ -96,5 +99,5 @@ export default function calcTextareaHeight(
height = Math.min(maxHeight, height);
}
return { height: height + 'px'};
return merge({ height: height + 'px'}, options);
};

View File

@ -88,6 +88,7 @@
value: [String, Number],
placeholder: String,
size: String,
resize: String,
readonly: Boolean,
autofocus: Boolean,
icon: String,
@ -149,7 +150,10 @@
const minRows = autosize.minRows;
const maxRows = autosize.maxRows;
this.textareaStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
const options = {
resize: this.resize
};
this.textareaStyle = calcTextareaHeight(this.$refs.textarea, minRows, maxRows, options);
},
handleFocus(event) {
this.$emit('focus', event);

View File

@ -36,37 +36,40 @@ exports.install = Vue => {
});
} else {
if (el.domVisible) {
el.mask.style.display = 'none';
el.domVisible = false;
if (binding.modifiers.fullscreen && el.originalOverflow !== 'hidden') {
document.body.style.overflow = el.originalOverflow;
}
if (binding.modifiers.fullscreen || binding.modifiers.body) {
document.body.style.position = el.originalPosition;
} else {
el.style.position = el.originalPosition;
}
el.instance.$on('after-leave', _ => {
el.domVisible = false;
if (binding.modifiers.fullscreen && el.originalOverflow !== 'hidden') {
document.body.style.overflow = el.originalOverflow;
}
if (binding.modifiers.fullscreen || binding.modifiers.body) {
document.body.style.position = el.originalPosition;
} else {
el.style.position = el.originalPosition;
}
});
el.instance.visible = false;
}
}
};
let insertDom = (parent, directive, binding) => {
if (!directive.domVisible) {
Object.keys(directive.maskStyle).forEach(property => {
directive.mask.style[property] = directive.maskStyle[property];
let insertDom = (parent, el, binding) => {
if (!el.domVisible) {
Object.keys(el.maskStyle).forEach(property => {
el.mask.style[property] = el.maskStyle[property];
});
if (directive.originalPosition !== 'absolute') {
if (el.originalPosition !== 'absolute') {
parent.style.position = 'relative';
}
if (binding.modifiers.fullscreen && binding.modifiers.lock) {
parent.style.overflow = 'hidden';
}
directive.mask.style.display = 'block';
directive.domVisible = true;
el.domVisible = true;
parent.appendChild(directive.mask);
directive.domInserted = true;
parent.appendChild(el.mask);
Vue.nextTick(() => {
el.instance.visible = true;
});
el.domInserted = true;
}
};
@ -79,6 +82,7 @@ exports.install = Vue => {
fullscreen: !!binding.modifiers.fullscreen
}
});
el.instance = mask;
el.mask = mask.$el;
el.maskStyle = {};

View File

@ -29,10 +29,13 @@ LoadingConstructor.prototype.close = function() {
if (this.fullscreen) {
fullscreenLoading = undefined;
}
this.$el &&
this.$el.parentNode &&
this.$el.parentNode.removeChild(this.$el);
this.$destroy();
this.$on('after-leave', _ => {
this.$el &&
this.$el.parentNode &&
this.$el.parentNode.removeChild(this.$el);
this.$destroy();
});
this.visible = false;
};
const addStyle = (options, parent, instance) => {
@ -90,6 +93,9 @@ const Loading = (options = {}) => {
parent.style.overflow = 'hidden';
}
parent.appendChild(instance.$el);
Vue.nextTick(() => {
instance.visible = true;
});
if (options.fullscreen) {
fullscreenLoading = instance;
}

View File

@ -1,12 +1,17 @@
<template>
<div class="el-loading-mask" :class="[customClass, { 'is-fullscreen': fullscreen }]">
<div class="el-loading-spinner">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none"/>
</svg>
<p v-if="text" class="el-loading-text">{{ text }}</p>
<transition name="el-loading-fade" @after-leave="handleAfterLeave">
<div
v-show="visible"
class="el-loading-mask"
:class="[customClass, { 'is-fullscreen': fullscreen }]">
<div class="el-loading-spinner">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none"/>
</svg>
<p v-if="text" class="el-loading-text">{{ text }}</p>
</div>
</div>
</div>
</transition>
</template>
<script>
@ -15,8 +20,15 @@
return {
text: null,
fullscreen: true,
visible: false,
customClass: ''
};
},
methods: {
handleAfterLeave() {
this.$emit('after-leave');
}
}
};
</script>

View File

@ -11,12 +11,14 @@
</template>
<script>
import Menu from './menu-mixin';
import Emitter from 'element-ui/src/mixins/emitter';
module.exports = {
name: 'ElMenuItem',
componentName: 'ElMenuItem',
mixins: [Menu],
mixins: [Menu, Emitter],
props: {
index: {
@ -34,21 +36,21 @@
},
computed: {
active() {
return this.index === this.rootMenu.activeIndex;
return this.index === this.rootMenu.activedIndex;
}
},
methods: {
handleClick() {
this.rootMenu.handleSelect(
this.index,
this.indexPath,
this.route || this.index,
this
);
this.dispatch('ElMenu', 'item-click', this);
}
},
created() {
this.rootMenu.menuItems[this.index] = this;
this.parentMenu.addItem(this);
this.rootMenu.addItem(this);
},
beforeDestroy() {
this.parentMenu.removeItem(this);
this.rootMenu.removeItem(this);
}
};
</script>

View File

@ -13,7 +13,20 @@ module.exports = {
},
rootMenu() {
var parent = this.$parent;
while (parent.$options.componentName !== 'ElMenu') {
while (
parent &&
parent.$options.componentName !== 'ElMenu'
) {
parent = parent.$parent;
}
return parent;
},
parentMenu() {
let parent = this.$parent;
while (
parent &&
['ElMenu', 'ElSubmenu'].indexOf(parent.$options.componentName) === -1
) {
parent = parent.$parent;
}
return parent;

View File

@ -41,26 +41,46 @@
},
data() {
return {
activeIndex: this.defaultActive,
activedIndex: this.defaultActive,
openedMenus: this.defaultOpeneds ? this.defaultOpeneds.slice(0) : [],
menuItems: {},
items: {},
submenus: {}
};
},
watch: {
defaultActive(value) {
this.activeIndex = value;
if (!this.menuItems[value]) return;
let menuItem = this.menuItems[value];
let indexPath = menuItem.indexPath;
const item = this.items[value];
if (!item) return;
this.handleSelect(value, indexPath, null, menuItem);
this.activedIndex = item.index;
this.initOpenedMenu();
},
defaultOpeneds(value) {
this.openedMenus = value;
},
'$route': {
immediate: true,
handler(value) {
if (this.router) {
this.activedIndex = value.path;
this.initOpenedMenu();
}
}
}
},
methods: {
addItem(item) {
this.$set(this.items, item.index, item);
},
removeItem(item) {
delete this.items[item.index];
},
addSubmenu(item) {
this.$set(this.submenus, item.index, item);
},
removeSubmenu(item) {
delete this.submenus[item.index];
},
openMenu(index, indexPath) {
let openedMenus = this.openedMenus;
if (openedMenus.indexOf(index) !== -1) return;
@ -75,7 +95,8 @@
closeMenu(index, indexPath) {
this.openedMenus.splice(this.openedMenus.indexOf(index), 1);
},
handleSubmenuClick(index, indexPath) {
handleSubmenuClick(submenu) {
const { index, indexPath } = submenu;
let isOpened = this.openedMenus.indexOf(index) !== -1;
if (isOpened) {
@ -86,49 +107,48 @@
this.$emit('open', index, indexPath);
}
},
handleSelect(index, indexPath, route, instance) {
this.activeIndex = index;
this.$emit('select', index, indexPath, instance);
handleItemClick(item) {
let { index, indexPath } = item;
this.$emit('select', index, indexPath, item);
if (this.mode === 'horizontal') {
this.broadcast('ElSubmenu', 'item-select', [index, indexPath]);
this.openedMenus = [];
} else {
this.openActiveItemMenus();
}
if (this.router && route) {
try {
this.$router.push(route);
} catch (e) {
console.error(e);
}
if (this.router) {
this.routeToItem(item);
} else {
this.activedIndex = item.index;
}
},
openActiveItemMenus() {
let index = this.activeIndex;
// menu
if (this.router) {
const userSpecifiedIndexs = Object
.keys(this.menuItems)
.filter(k => this.menuItems[k].route)
.filter(k => this.menuItems[k].route.path === this.$route.path);
userSpecifiedIndexs.length && (index = this.activeIndex = userSpecifiedIndexs[0]);
}
if (!this.menuItems[index]) return;
if (index && this.mode === 'vertical') {
let indexPath = this.menuItems[index].indexPath;
//
initOpenedMenu() {
const index = this.activedIndex;
const activeItem = this.items[index];
if (!activeItem || this.mode === 'horizontal') return;
//
indexPath.forEach(index => {
let submenu = this.submenus[index];
submenu && this.openMenu(index, submenu.indexPath);
});
let indexPath = activeItem.indexPath;
//
indexPath.forEach(index => {
let submenu = this.submenus[index];
submenu && this.openMenu(index, submenu.indexPath);
});
},
routeToItem(item) {
let route = item.route || item.index;
try {
this.$router.push(route);
} catch (e) {
console.error(e);
}
}
},
mounted() {
this.openActiveItemMenus();
this.initOpenedMenu();
this.$on('item-click', this.handleItemClick);
this.$on('submenu-click', this.handleSubmenuClick);
}
};
</script>

View File

@ -15,20 +15,31 @@
}">
</i>
</div>
<transition :name="rootMenu.mode === 'horizontal' ? 'el-zoom-in-top' : ''">
<template v-if="rootMenu.mode === 'horizontal'">
<transition name="el-zoom-in-top">
<ul class="el-menu" v-show="opened"><slot></slot></ul>
</transition>
</template>
<collapse-transition v-else>
<ul class="el-menu" v-show="opened"><slot></slot></ul>
</transition>
</collapse-transition>
</li>
</template>
<script>
import menuMixin from './menu-mixin';
import Emitter from 'element-ui/src/mixins/emitter';
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
module.exports = {
name: 'ElSubmenu',
componentName: 'ElSubmenu',
mixins: [menuMixin],
mixins: [menuMixin, Emitter],
components: {
CollapseTransition
},
props: {
index: {
@ -39,17 +50,52 @@
data() {
return {
timeout: null,
active: false
items: {},
submenus: {}
};
},
computed: {
opened() {
return this.rootMenu.openedMenus.indexOf(this.index) !== -1;
return this.rootMenu.openedMenus.indexOf(this.index) > -1;
},
active: {
cache: false,
get() {
let isActive = false;
const submenus = this.submenus;
const items = this.items;
Object.keys(items).forEach(index => {
if (items[index].active) {
isActive = true;
}
});
Object.keys(submenus).forEach(index => {
if (submenus[index].active) {
isActive = true;
}
});
return isActive;
}
}
},
methods: {
addItem(item) {
this.$set(this.items, item.index, item);
},
removeItem(item) {
delete this.items[item.index];
},
addSubmenu(item) {
this.$set(this.submenus, item.index, item);
},
removeSubmenu(item) {
delete this.submenus[item.index];
},
handleClick() {
this.rootMenu.handleSubmenuClick(this.index, this.indexPath);
this.dispatch('ElMenu', 'submenu-click', this);
},
handleMouseenter() {
clearTimeout(this.timeout);
@ -83,12 +129,14 @@
}
},
created() {
this.rootMenu.submenus[this.index] = this;
this.parentMenu.addSubmenu(this);
this.rootMenu.addSubmenu(this);
},
beforeDestroy() {
this.parentMenu.removeSubmenu(this);
this.rootMenu.removeSubmenu(this);
},
mounted() {
this.$on('item-select', (index, indexPath) => {
this.active = indexPath.indexOf(this.index) !== -1;
});
this.initEvents();
}
};

View File

@ -20,7 +20,8 @@ const defaults = {
confirmButtonText: '',
cancelButtonText: '',
confirmButtonClass: '',
cancelButtonClass: ''
cancelButtonClass: '',
beforeClose: null
};
import Vue from 'vue';
@ -87,6 +88,12 @@ const showNextMsg = () => {
if (options.callback === undefined) {
instance.callback = defaultCallback;
}
let oldCb = instance.callback;
instance.callback = action => {
oldCb(action);
showNextMsg();
};
['modal', 'showClose', 'closeOnClickModal', 'closeOnPressEscape'].forEach(prop => {
if (instance[prop] === undefined) {
instance[prop] = true;

View File

@ -15,8 +15,21 @@
</div>
</div>
<div class="el-message-box__btns">
<el-button :class="[ cancelButtonClasses ]" v-show="showCancelButton" @click.native="handleAction('cancel')">{{ cancelButtonText || t('el.messagebox.cancel') }}</el-button>
<el-button ref="confirm" :class="[ confirmButtonClasses ]" v-show="showConfirmButton" @click.native="handleAction('confirm')">{{ confirmButtonText || t('el.messagebox.confirm') }}</el-button>
<el-button
:loading="cancelButtonLoading"
:class="[ cancelButtonClasses ]"
v-show="showCancelButton"
@click.native="handleAction('cancel')">
{{ cancelButtonText || t('el.messagebox.cancel') }}
</el-button>
<el-button
:loading="confirmButtonLoading"
ref="confirm"
:class="[ confirmButtonClasses ]"
v-show="showConfirmButton"
@click.native="handleAction('confirm')">
{{ confirmButtonText || t('el.messagebox.confirm') }}
</el-button>
</div>
</div>
</div>
@ -79,7 +92,16 @@
},
methods: {
getSafeClose() {
const currentId = this.uid;
return () => {
this.$nextTick(() => {
if (currentId === this.uid) this.doClose();
});
};
},
doClose() {
if (!this.value) return;
this.value = false;
this._closing = true;
@ -100,11 +122,13 @@
if (!this.transition) {
this.doAfterClose();
}
if (this.action) this.callback(this.action, this);
},
handleWrapperClick() {
if (this.closeOnClickModal) {
this.close();
this.action = '';
this.doClose();
}
},
@ -112,9 +136,13 @@
if (this.$type === 'prompt' && action === 'confirm' && !this.validate()) {
return;
}
var callback = this.callback;
this.value = false;
callback(action);
this.action = action;
if (typeof this.beforeClose === 'function') {
this.close = this.getSafeClose();
this.beforeClose(action, this, this.close);
} else {
this.doClose();
}
},
validate() {
@ -153,6 +181,7 @@
},
value(val) {
if (val) this.uid++;
if (this.$type === 'alert' || this.$type === 'confirm') {
this.$nextTick(() => {
this.$refs.confirm.$el.focus();
@ -174,6 +203,7 @@
data() {
return {
uid: 1,
title: undefined,
message: '',
type: '',
@ -186,8 +216,11 @@
inputErrorMessage: '',
showConfirmButton: true,
showCancelButton: false,
action: '',
confirmButtonText: '',
cancelButtonText: '',
confirmButtonLoading: false,
cancelButtonLoading: false,
confirmButtonClass: '',
confirmButtonDisabled: false,
cancelButtonClass: '',

View File

@ -1,5 +1,6 @@
import Vue from 'vue';
import { PopupManager } from 'element-ui/src/utils/popup';
import { isVNode } from 'element-ui/src/utils/vdom';
let NotificationConstructor = Vue.extend(require('./main.vue'));
let instance;
@ -19,6 +20,11 @@ var Notification = function(options) {
instance = new NotificationConstructor({
data: options
});
if (isVNode(options.message)) {
instance.$slots.default = [options.message];
options.message = '';
}
instance.id = id;
instance.vm = instance.$mount();
document.body.appendChild(instance.vm.$el);
@ -39,7 +45,7 @@ var Notification = function(options) {
['success', 'warning', 'info', 'error'].forEach(type => {
Notification[type] = options => {
if (typeof options === 'string') {
if (typeof options === 'string' || isVNode(options)) {
options = {
message: options
};

View File

@ -13,8 +13,8 @@
v-if="type || iconClass">
</i>
<div class="el-notification__group" :class="{ 'is-with-icon': typeClass || iconClass }">
<span>{{ title }}</span>
<p>{{ message }}</p>
<h2 class="el-notification__title" v-text="title"></h2>
<div class="el-notification__content"><slot>{{ message }}</slot></div>
<div class="el-notification__closeBtn el-icon-close" @click="close"></div>
</div>
</div>

View File

@ -5,7 +5,7 @@
class="el-popover"
:class="[popperClass]"
ref="popper"
v-show="showPopper"
v-show="!disabled && showPopper"
:style="{ width: width + 'px' }">
<div class="el-popover__title" v-if="title" v-text="title"></div>
<slot>{{ content }}</slot>
@ -31,6 +31,7 @@ export default {
validator: value => ['click', 'focus', 'hover', 'manual'].indexOf(value) > -1
},
title: String,
disabled: Boolean,
content: String,
reference: {},
popperClass: String,

View File

@ -88,10 +88,10 @@
watch: {
currentLabel() {
this.dispatch('ElSelect', 'setSelected');
if (!this.created) this.dispatch('ElSelect', 'setSelected');
},
value() {
this.dispatch('ElSelect', 'setSelected');
if (!this.created) this.dispatch('ElSelect', 'setSelected');
}
},
@ -114,7 +114,7 @@
queryChange(query) {
// query
let parsedQuery = query.replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, '\\$1');
let parsedQuery = String(query).replace(/(\^|\(|\)|\[|\]|\$|\*|\+|\.|\?|\\|\{|\}|\|)/g, '\\$1');
this.visible = new RegExp(parsedQuery, 'i').test(this.currentLabel) || this.created;
if (!this.visible) {
this.parent.filteredOptionsCount--;

View File

@ -49,7 +49,7 @@
:disabled="disabled"
:readonly="!filterable || multiple"
:validate-event="false"
@focus="toggleMenu"
@focus="handleFocus"
@click="handleIconClick"
@mousedown.native="handleMouseDown"
@keyup.native="debouncedOnInputChange"
@ -98,6 +98,7 @@
import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import { t } from 'element-ui/src/locale';
import merge from 'element-ui/src/utils/merge';
const sizeMap = {
'large': 42,
'small': 30,
@ -191,6 +192,8 @@
return {
options: [],
cachedOptions: [],
createdOption: null,
createdSelected: false,
selected: this.multiple ? [] : {},
isSelect: true,
inputLength: 20,
@ -265,6 +268,7 @@
}
this.query = '';
this.selectedLabel = '';
this.inputLength = 20;
this.resetHoverIndex();
this.$nextTick(() => {
if (this.$refs.input &&
@ -276,7 +280,12 @@
if (!this.multiple) {
this.getOverflows();
if (this.selected) {
this.selectedLabel = this.selected.currentLabel;
if (this.filterable && this.allowCreate &&
this.createdSelected && this.createdOption) {
this.selectedLabel = this.createdOption.currentLabel;
} else {
this.selectedLabel = this.selected.currentLabel;
}
if (this.filterable) this.query = this.selectedLabel;
}
}
@ -371,8 +380,15 @@
setSelected() {
if (!this.multiple) {
let option = this.getOption(this.value);
if (option.created) {
this.createdOption = merge({}, option);
this.createdSelected = true;
} else {
this.createdSelected = false;
}
this.selectedLabel = option.currentLabel;
this.selected = option;
if (this.filterable) this.query = this.selectedLabel;
return;
}
let result = [];
@ -382,6 +398,13 @@
});
}
this.selected = result;
this.$nextTick(() => {
this.resetInputHeight();
});
},
handleFocus() {
this.visible = true;
},
handleIconClick(event) {

View File

@ -8,6 +8,7 @@
ref="input"
:step="step"
:disabled="disabled"
:controls="showInputControls"
:min="min"
:max="max"
size="small">
@ -67,6 +68,10 @@
type: Boolean,
default: false
},
showInputControls: {
type: Boolean,
default: true
},
showStops: {
type: Boolean,
default: false

View File

@ -37,7 +37,7 @@ Vue.component('el-step', ElStep)
| active | 设置当前激活步骤 | number | — | 0 |
| process-status | 设置当前步骤的状态 | string | wait/process/finish/error/success | process |
| finish-status | 设置结束步骤的状态 | string | wait/process/finish/error/success | finish |
| align-center | 标题描述居中对齐 | boolean | false, true | false |
| align-center | 标题描述居中对齐 | boolean | - | false |
### Step Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -1,14 +1,15 @@
<template>
<div
class="el-step"
:style="style"
:style="[style, isLast ? '' : { marginRight: - $parent.stepOffset + 'px' }]"
:class="['is-' + $parent.direction]">
<div
class="el-step__head"
:class="['is-' + currentStatus, { 'is-text': !icon }]">
<div
class="el-step__line"
:class="['is-' + $parent.direction,{ 'is-icon': icon }]">
:style="isLast ? '' : { marginRight: $parent.stepOffset + 'px' }"
:class="['is-' + $parent.direction, { 'is-icon': icon }]">
<i class="el-step__line-inner" :style="lineStyle"></i>
</div>
@ -63,6 +64,7 @@ export default {
style: {},
lineStyle: {},
mainOffset: 0,
isLast: false,
currentStatus: this.status
};
},
@ -103,22 +105,31 @@ export default {
: style.width = step + '%';
this.lineStyle = style;
},
adjustPosition() {
this.style = {};
this.$parent.stepOffset = this.$el.getBoundingClientRect().width / (this.$parent.steps.length - 1);
}
},
mounted() {
const parent = this.$parent;
const isCenter = parent.center;
const len = parent.steps.length;
const isLast = this.isLast = parent.steps[parent.steps.length - 1] === this;
const space = parent.space
? parent.space + 'px'
: 100 / parent.steps.length + '%';
: 100 / (isCenter ? len - 1 : len) + '%';
if (parent.direction === 'horizontal') {
this.style = { width: space };
if (parent.alignCenter) {
this.mainOffset = -this.$refs.title.getBoundingClientRect().width / 2 + 16 + 'px';
}
isCenter && isLast && this.adjustPosition();
} else {
if (parent.steps[parent.steps.length - 1] !== this) {
if (!isLast) {
this.style = { height: space };
}
}

View File

@ -1,5 +1,9 @@
<template>
<div class="el-steps" :class="['is-' + direction]"><slot></slot></div>
<div
class="el-steps"
:class="['is-' + direction, center ? 'is-center' : '']">
<slot></slot>
</div>
</template>
<script>
@ -14,6 +18,7 @@ export default {
default: 'horizontal'
},
alignCenter: Boolean,
center: Boolean,
finishStatus: {
type: String,
default: 'finish'
@ -26,7 +31,8 @@ export default {
data() {
return {
steps: []
steps: [],
stepOffset: 0
};
},

View File

@ -28,13 +28,15 @@ export default {
cellspacing="0"
cellpadding="0"
border="0">
{
this._l(this.columns, column =>
<col
name={ column.id }
width={ column.realWidth || column.width }
/>)
}
<colgroup>
{
this._l(this.columns, column =>
<col
name={ column.id }
width={ column.realWidth || column.width }
/>)
}
</colgroup>
<tbody>
{
this._l(this.data, (row, $index) =>
@ -114,7 +116,7 @@ export default {
computed: {
table() {
return this.$parent.$parent.columns ? this.$parent.$parent : this.$parent;
return this.$parent;
},
data() {

View File

@ -143,6 +143,7 @@ export default {
selectable: Function,
reserveSelection: Boolean,
filterMethod: Function,
filteredValue: Array,
filters: Array,
filterMultiple: {
type: Boolean,
@ -235,7 +236,7 @@ export default {
filterable: this.filters || this.filterMethod,
filterMultiple: this.filterMultiple,
filterOpened: false,
filteredValue: []
filteredValue: this.filteredValue || []
});
objectAssign(column, forced[type] || {});
@ -335,12 +336,16 @@ export default {
align(newVal) {
if (this.columnConfig) {
this.columnConfig.align = newVal ? 'is-' + newVal : null;
if (!this.headerAlign) {
this.columnConfig.headerAlign = newVal ? 'is-' + newVal : null;
}
}
},
headerAlign(newVal) {
if (this.columnConfig) {
this.columnConfig.headerAlign = newVal ? 'is-' + newVal : this.align;
this.columnConfig.headerAlign = 'is-' + (newVal ? newVal : this.align);
}
},

View File

@ -78,18 +78,20 @@ export default {
cellspacing="0"
cellpadding="0"
border="0">
{
this._l(this.columns, column =>
<col
name={ column.id }
width={ column.realWidth || column.width }
/>)
}
{
!this.fixed && this.layout.gutterWidth
? <col name="gutter" width={ this.layout.scrollY ? this.layout.gutterWidth : '' }></col>
: ''
}
<colgroup>
{
this._l(this.columns, column =>
<col
name={ column.id }
width={ column.realWidth || column.width }
/>)
}
{
!this.fixed && this.layout.gutterWidth
? <col name="gutter" width={ this.layout.scrollY ? this.layout.gutterWidth : '' }></col>
: ''
}
</colgroup>
<thead>
{
this._l(columnRows, (columns, rowIndex) =>
@ -112,9 +114,9 @@ export default {
}
{
column.sortable
? <span class="caret-wrapper">
<i class="sort-caret ascending" on-click={ ($event) => this.handleHeaderClick($event, column, 'ascending')}></i>
<i class="sort-caret descending" on-click={ ($event) => this.handleHeaderClick($event, column, 'descending')}></i>
? <span class="caret-wrapper" on-click={ ($event) => this.handleHeaderClick($event, column) }>
<i class="sort-caret ascending"></i>
<i class="sort-caret descending"></i>
</span>
: ''
}
@ -148,7 +150,12 @@ export default {
layout: {
required: true
},
border: Boolean
border: Boolean,
defaultSortProp: String,
defaultSortOrder: {
type: String,
default: 'ascending'
}
},
components: {
@ -182,6 +189,29 @@ export default {
this.filterPanels = {};
},
mounted() {
if (this.defaultSortProp) {
const states = this.store.states;
states.sortProp = this.defaultSortProp;
states.sortOrder = this.defaultSortOrder;
this.$nextTick(_ => {
for (let i = 0, length = this.columns.length; i < length; i++) {
let column = this.columns[i];
if (column.property === this.defaultSortProp) {
column.order = this.defaultSortOrder;
states.sortingColumn = column;
break;
}
}
if (states.sortingColumn) {
this.store.commit('changeSortCondition');
}
});
}
},
beforeDestroy() {
const panels = this.filterPanels;
for (let prop in panels) {
@ -334,7 +364,16 @@ export default {
document.body.style.cursor = '';
},
handleHeaderClick(event, column, order) {
toggleOrder(column) {
if (column.order === 'ascending') {
return 'descending';
}
return 'ascending';
},
handleHeaderClick(event, column) {
let order = this.toggleOrder(column);
let target = event.target;
while (target && target.tagName !== 'TH') {
target = target.parentNode;

View File

@ -69,6 +69,7 @@ class TableLayout {
updateHeight() {
const height = this.tableHeight = this.table.$el.clientHeight;
const noData = !this.table.data || this.table.data.length === 0;
const { headerWrapper } = this.table.$refs;
if (this.showHeader && !headerWrapper) return;
if (!this.showHeader) {
@ -85,7 +86,7 @@ class TableLayout {
}
this.fixedBodyHeight = this.scrollX ? bodyHeight - this.gutterWidth : bodyHeight;
}
this.viewportHeight = this.scrollX ? height - this.gutterWidth : height;
this.viewportHeight = this.scrollX ? height - (noData ? 0 : this.gutterWidth) : height;
}
update() {

View File

@ -15,6 +15,8 @@
:store="store"
:layout="layout"
:border="border"
:default-sort-prop="defaultSortProp"
:default-sort-order="defaultSortOrder"
:style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
</table-header>
</div>
@ -29,9 +31,9 @@
:row-class-name="rowClassName"
:row-style="rowStyle"
:highlight="highlightCurrentRow"
:style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }">
:style="{ width: bodyWidth }">
</table-body>
<div class="el-table__empty-block" v-if="!data || data.length === 0">
<div :style="{ width: bodyWidth }" class="el-table__empty-block" v-if="!data || data.length === 0">
<span class="el-table__empty-text"><slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot></span>
</div>
</div>
@ -166,7 +168,11 @@
expandRowKeys: Array,
defaultExpandAll: Boolean
defaultExpandAll: Boolean,
defaultSortProp: String,
defaultSortOrder: String
},
components: {
@ -291,6 +297,11 @@
return style;
},
bodyWidth() {
const { bodyWidth, scrollY, gutterWidth } = this.layout;
return bodyWidth ? bodyWidth - (scrollY ? gutterWidth : 0) + 'px' : '';
},
fixedBodyHeight() {
let style = {};

View File

@ -0,0 +1,42 @@
<template>
<div class="el-tabs__active-bar" :style="barStyle"></div>
</template>
<script>
export default {
props: {
tabs: Array
},
computed: {
barStyle: {
cache: false,
get() {
if (!this.$parent.$refs.tabs) return {};
let style = {};
let offset = 0;
let tabWidth = 0;
this.tabs.every((tab, index) => {
let $el = this.$parent.$refs.tabs[index];
if (!$el) { return false; }
if (!tab.active) {
offset += $el.clientWidth;
return true;
} else {
tabWidth = $el.clientWidth;
return false;
}
});
const transform = `translateX(${offset}px)`;
style.width = tabWidth + 'px';
style.transform = transform;
style.msTransform = transform;
style.webkitTransform = transform;
return style;
}
}
}
};
</script>

View File

@ -1,14 +1,14 @@
<template>
<div class="el-tab-pane">
<div class="el-tab-pane__content" v-show="active">
<slot></slot>
</div>
<div class="el-tab-pane" v-show="active">
<slot></slot>
</div>
</template>
<script>
module.exports = {
name: 'ElTabPane',
componentName: 'ElTabPane',
props: {
label: String,
labelContent: Function,
@ -32,14 +32,15 @@
}
},
created() {
this.$parent.$forceUpdate();
mounted() {
this.$parent.addPanes(this);
},
destroyed() {
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el);
}
this.$parent.removePanes(this);
},
watch: {

View File

@ -1,7 +1,12 @@
<script>
import TabBar from './tab-bar';
module.exports = {
name: 'ElTabs',
components: {
TabBar
},
props: {
type: String,
activeName: String,
@ -15,7 +20,8 @@
data() {
return {
children: null,
currentName: this.value || this.activeName
currentName: this.value || this.activeName,
panes: []
};
},
@ -30,9 +36,8 @@
computed: {
currentTab() {
if (!this.$children) return;
let result;
this.$children.forEach(tab => {
this.panes.forEach(tab => {
if (this.currentName === (tab.name || tab.index)) {
result = tab;
}
@ -42,21 +47,25 @@
},
methods: {
handleTabRemove(tab, event) {
handleTabRemove(pane, event) {
event.stopPropagation();
const tabs = this.$children;
const panes = this.panes;
const currentTab = this.currentTab;
let index = tabs.indexOf(tab);
tab.$destroy();
let index = panes.indexOf(pane);
this.$emit('tab-remove', tab);
this.$forceUpdate();
if (index === -1) return;
panes.splice(index, 1);
pane.$destroy();
this.$emit('tab-remove', pane);
this.$nextTick(_ => {
if (tab.active) {
let nextChild = tabs[index];
let prevChild = tabs[index - 1];
if (pane.active) {
const panes = this.panes;
let nextChild = panes[index];
let prevChild = panes[index - 1];
let nextActiveTab = nextChild || prevChild || null;
if (nextActiveTab) {
@ -76,80 +85,58 @@
setCurrentName(value) {
this.currentName = value;
this.$emit('input', value);
},
addPanes(item) {
this.panes.push(item);
},
removePanes(item) {
const panes = this.panes;
const index = panes.indexOf(item);
if (index > -1) {
panes.splice(index, 1);
}
}
},
mounted() {
this.$forceUpdate();
},
render(h) {
let {
type,
handleTabRemove,
handleTabClick,
currentName
currentName,
panes
} = this;
const getBarStyle = () => {
if (this.type || !this.$refs.tabs) return {};
let style = {};
let offset = 0;
let tabWidth = 0;
this.$children.every((tab, index) => {
let $el = this.$refs.tabs[index];
if (!$el) { return false; }
if (!tab.active) {
offset += $el.clientWidth;
return true;
} else {
tabWidth = $el.clientWidth;
return false;
}
});
style.width = tabWidth + 'px';
style.transform = `translateX(${offset}px)`;
return style;
};
const tabs = this.$children.map((tab, index) => {
let tabName = tab.name || tab.index || index;
const tabs = this._l(panes, (pane, index) => {
let tabName = pane.name || pane.index || index;
if (currentName === undefined && index === 0) {
this.setCurrentName(tabName);
}
tab.index = index;
pane.index = index;
const activeBar = !type && index === 0
? <div class="el-tabs__active-bar" style={getBarStyle()}></div>
const btnClose = pane.isClosable
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(pane, ev); }}></span>
: null;
const btnClose = tab.isClosable
? <span class="el-icon-close" on-click={(ev) => { handleTabRemove(tab, ev); }}></span>
: null;
const tabLabelContent = tab.$slots.label || tab.label;
const tabLabelContent = pane.$slots.label || pane.label;
return (
<div
class={{
'el-tabs__item': true,
'is-active': tab.active,
'is-disabled': tab.disabled,
'is-closable': tab.isClosable
'is-active': pane.active,
'is-disabled': pane.disabled,
'is-closable': pane.isClosable
}}
ref="tabs"
refInFor
on-click={(ev) => { handleTabClick(tab, tabName, ev); }}
on-click={(ev) => { handleTabClick(pane, tabName, ev); }}
>
{tabLabelContent}
{btnClose}
{activeBar}
</div>
);
});
return (
<div class={{
'el-tabs': true,
@ -157,6 +144,7 @@
'el-tabs--border-card': type === 'border-card'
}}>
<div class="el-tabs__header">
{!type ? <tab-bar tabs={panes}></tab-bar> : null}
{tabs}
</div>
<div class="el-tabs__content">

View File

@ -1,6 +1,6 @@
{
"name": "element-theme-default",
"version": "1.1.2",
"version": "1.1.3",
"description": "Element component default theme.",
"main": "lib/index.css",
"style": "lib/index.css",

View File

@ -12,7 +12,7 @@
position: relative;
background-color: var(--color-white);
overflow: hidden;
color: #fff;
color: var(--color-white);
opacity: 1;
display: table;
transition: opacity .2s;
@ -59,14 +59,14 @@
}
& .el-alert__description {
color: #fff;
color: var(--color-white);
font-size: var(--alert-description-font-size);
margin: 5px 0 0 0;
}
@e closebtn {
font-size: var(--alert-close-font-size);
color: #fff;
color: var(--color-white);
opacity: 1;
position: absolute 12px 15px * *;
cursor: pointer;

View File

@ -12,8 +12,8 @@
left: 0;
top: 110%;
margin: 5px 0 0;
background-color: #fff;
border: 1px solid #D3DCE6;
background-color: var(--color-white);
border: 1px solid var(--color-base-gray);
width: 100%;
padding: 6px 0;
z-index: 10;
@ -29,7 +29,7 @@
padding: 0 10px;
margin: 0;
cursor: pointer;
color: #475669;
color: var(--color-extra-light-black);
font-size: 14px;
white-space: nowrap;
overflow: hidden;
@ -40,14 +40,14 @@
}
&.highlighted {
background-color: var(--color-primary);
color: #fff;
color: var(--color-white);
}
&:active {
background-color: darken(var(--color-primary), 0.2);
}
&.divider {
margin-top: 6px;
border-top: 1px solid #D3DCE6;
border-top: 1px solid var(--color-base-gray);
}
&.divider:last-child {
margin-bottom: -6px;
@ -64,7 +64,7 @@
@utils-vertical-center;
&:hover {
background-color: #fff;
background-color: var(--color-white);
}
}

View File

@ -10,7 +10,7 @@
@e content {
background-color: var(--badge-fill);
border-radius: var(--badge-radius);
color: #fff;
color: var(--color-white);
display: inline-block;
font-size: var(--badge-font-size);
height: var(--badge-size);
@ -18,7 +18,7 @@
padding: 0 var(--badge-padding);
text-align: center;
white-space: nowrap;
border: 1px solid #fff;
border: 1px solid var(--color-white);
@when fixed {
position: absolute 0 calc(var(--badge-size) / 2 + 1) * *;

View File

@ -10,7 +10,7 @@
@e separator {
margin: 0 8px;
color: #c0ccda;
color: var(--color-extra-light-silver);
}
@e item {
float: left;
@ -18,7 +18,7 @@
@e inner {
&, & a {
transition: color .15s linear;
color:#475669;
color:var(--color-extra-light-black);
&:hover {
color: var(--color-primary);
@ -31,7 +31,7 @@
.el-breadcrumb__item__inner,
.el-breadcrumb__item__inner a {
&, &:hover {
color: #99a9bf;
color: var(--color-light-silver);
cursor: text;
}
}

View File

@ -48,13 +48,13 @@
@when plain {
&:hover,
&:focus {
background: #fff;
background: var(--color-white);
border-color: var(--color-primary);
color: var(--color-primary);
}
&:active {
background: #fff;
background: var(--color-white);
border-color: shade(var(--color-primary), var(--button-active-shade-percent));
color: shade(var(--color-primary), var(--button-active-shade-percent));
outline: none;
@ -85,9 +85,9 @@
&,
&:hover,
&:focus {
background-color: #fff;
border-color: #d3dce6;
color: #C0CCDA;
background-color: var(--color-white);
border-color: var(--color-base-gray);
color: var(--color-extra-light-silver);
}
}
}
@ -190,14 +190,14 @@
@each $type in (primary, success, warning, danger, info) {
.el-button--$type {
&:first-child {
border-right-color: rgba(#fff, 0.5);
border-right-color: rgba(var(--color-white), 0.5);
}
&:last-child {
border-left-color: rgba(#fff, 0.5);
border-left-color: rgba(var(--color-white), 0.5);
}
&:not(:first-child):not(:last-child) {
border-left-color: rgba(#fff, 0.5);
border-right-color: rgba(#fff, 0.5);
border-left-color: rgba(var(--color-white), 0.5);
border-right-color: rgba(var(--color-white), 0.5);
}
}
}

View File

@ -5,7 +5,7 @@
@b card {
border: 1px solid var(--card-border-color);
border-radius: var(--card-border-radius);
background-color: #fff;
background-color: var(--color-white);
overflow: hidden;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, .12),
0px 0px 6px 0px rgba(0, 0, 0, .04);

View File

@ -12,33 +12,44 @@
/* Colors
-------------------------- */
--color-primary: #20a0ff;
--color-success: #13ce66;
--color-warning: #f7ba2a;
--color-danger: #ff4949;
--color-info: #50bfff;
--color-blue: #2e90fe;
--color-blue-light: #5da9ff;
--color-blue-lighter: rgba(var(--color-blue), 0.12);
--color-secondary: color(var(--color-primary) s(99%) l(*0.9));
--color-white: #fff;
--color-dark-white: color(var(--color-white) blend(var(--color-primary) 2%));
--color-black: #000;
--color-grey: #c0ccda;
--color-base-black: color(var(--color-primary) h(+6) s(33%) l(18%));
--color-light-black: color(var(--color-base-black) h(+5) s(27%) l(27%));
--color-extra-light-black: color(var(--color-base-black) h(+2) s(19%) l(35%));
--color-base-silver: color(var(--color-base-black) h(+3) s(16%) l(58%));
--color-light-silver: color(var(--color-base-black) h(+3) s(23%) l(67%));
--color-extra-light-silver: color(var(--color-base-black) s(26%) l(80%));
--color-base-gray: color(var(--color-base-black) s(28%) l(86%));
--color-light-gray: color(var(--color-base-black) h(+10) s(33%) l(92%));
--color-extra-light-gray: color(var(--color-base-black) h(+6) s(33%) l(95%));
/* Link
-------------------------- */
--link-color: #475669;
--link-color: var(--color-extra-light-black);
--link-hover-color: var(--color-primary);
/* Border
-------------------------- */
--border-width-base: 1px;
--border-style-base: solid;
--border-color-base: var(--color-grey);
--border-color-hover: #8492a6;
--border-color-base: var(--color-extra-light-silver);
--border-color-hover: var(--color-base-silver);
--border-base: var(--border-width-base) var(--border-style-base) var(--border-color-base);
--border-radius-base: 4px;
--border-radius-small: 2px;
--border-radius-circle: 100%;
--shadow-base: 0 0 2px rgba(var(--color-black), 0.18), 0 0 1px var(--color-blue-light);
/* Box-shadow
-------------------------- */
@ -52,7 +63,7 @@
/* Font
-------------------------- */
--font-size-base: 14px;
--font-color-base: #1f2d3d;
--font-color-base: var(--color-base-black);
--font-color-disabled-base: #bbb;
/* Size
@ -67,9 +78,9 @@
/* Disable base
-------------------------- */
--disabled-fill-base: #EFF2F7;
--disabled-fill-base: var(--color-extra-light-gray);
--disabled-color-base: #bbb;
--disabled-border-base: #D3DCE6;
--disabled-border-base: var(--color-base-gray);
/* Icon
-------------------------- */
@ -78,7 +89,7 @@
/* Checkbox
-------------------------- */
--checkbox-font-size: 14px;
--checkbox-color: #1f2d3d;
--checkbox-color: var(--color-base-black);
--checkbox-input-height: 18px;
--checkbox-input-width: 18px;
--checkbox-input-border-radius: var(--border-radius-base);
@ -95,17 +106,16 @@
--checkbox-disabled-checked-input-border-color: var(--disabled-border-base);
--checkbox-disabled-checked-icon-color: var(--color-white);
--checkbox-checked-input-border-color: var(--color-blue);
--checkbox-checked-input-border-color: var(--color-secondary);
--checkbox-checked-input-fill: var(--color-primary);
--checkbox-checked-icon-color: var(--fill-base);
--checkbox-input-shadow-hover: var(--shadow-base);
--checkbox-input-border-color-hover: var(--color-primary);
/* Radio
-------------------------- */
--radio-font-size: 14px;
--radio-color: #1f2d3d;
--radio-color: var(--color-base-black);
--radio-input-height: 18px;
--radio-input-width: 18px;
--radio-input-border-radius: var(--border-radius-circle);
@ -126,7 +136,6 @@
--radio-checked-input-fill: var(--color-white);
--radio-checked-icon-color: var(--color-primary);
--radio-input-shadow-hover: var(--shadow-base);
--radio-input-border-color-hover: var(--color-primary);
--radio-button-font-size: var(--font-size-base);
@ -136,9 +145,9 @@
--select-border-color-hover: var(--border-color-hover);
--select-disabled-border: var(--disabled-border-base);
--select-font-size: var(--font-size-base);
--select-close-hover-color: #99a9bf;
--select-close-hover-color: var(--color-light-silver);
--select-input-color: var(--color-grey);
--select-input-color: var(--color-extra-light-silver);
--select-multiple-input-color: #666;
--select-input-focus-background: var(--color-primary);
--select-input-font-size: 12px;
@ -148,11 +157,11 @@
--select-tag-background: var(--color-primary);
--select-option-color: var(--link-color);
--select-option-disabled-color: var(--color-grey);
--select-option-disabled-color: var(--color-extra-light-silver);
--select-option-height: 36px;
--select-option-hover-background: #e5e9f2;
--select-option-hover-background: var(--color-light-gray);
--select-option-selected: var(--color-primary);
--select-option-selected-hover: #1D8CE0;
--select-option-selected-hover: shade(var(--color-primary), 0.12);
--select-group-color: #999;
--select-group-height: 30px;
@ -203,8 +212,8 @@
--message-min-width: 300px;
--message-padding: 10px 12px;
--message-content-color: var(--border-color-hover);
--message-close-color: var(--color-grey);
--message-close-hover-color: #99A9BF;
--message-close-color: var(--color-extra-light-silver);
--message-close-hover-color: var(--color-light-silver);
--message-success-color: var(--color-success);
--message-info-color: var(--color-info);
@ -220,10 +229,10 @@
--notification-font-size: var(--font-size-base);
--notification-color: var(--border-color-hover);
--notification-title-font-size: 16px;
--notification-title-color: #1f2d3d;
--notification-title-color: var(--color-base-black);
--notification-close-color: var(--color-grey);
--notification-close-hover-color: #99A9BF;
--notification-close-color: var(--color-extra-light-silver);
--notification-close-hover-color: var(--color-light-silver);
--notification-success-color: var(--color-success);
--notification-info-color: var(--color-info);
@ -236,7 +245,6 @@
--input-color: var(--font-color-base);
--input-width: 140px;
--input-height: 36px;
--input-shadow-hover: var(--shadow-base);
--input-border: var(--border-base);
--input-border-color: var(--border-color-base);
--input-border-radius: var(--border-radius-base);
@ -244,8 +252,8 @@
--input-fill: var(--color-white);
--input-fill-disabled: var(--disabled-fill-base);
--input-color-disabled: var(--font-color-disabled-base);
--input-icon-color: var(--color-grey);
--input-placeholder-color: #99a9bf;
--input-icon-color: var(--color-extra-light-silver);
--input-placeholder-color: var(--color-light-silver);
--input-max-width: 314px;
--input-hover-border: var(--border-color-hover);
@ -256,7 +264,7 @@
--input-disabled-fill: var(--disabled-fill-base);
--input-disabled-border: var(--disabled-border-base);
--input-disabled-color: var(--disabled-color-base);
--input-disabled-placeholder-color: var(--color-grey);
--input-disabled-placeholder-color: var(--color-extra-light-silver);
--input-large-font-size: 16px;
--input-large-height: 42px;
@ -276,8 +284,8 @@
--cascader-menu-border-color: var(--border-color-base);
--cascader-menu-border-width: var(--border-width-base);
--cascader-menu-color: var(--font-color-base);
--cascader-menu-option-color-active: var(--color-blue);
--cascader-menu-option-fill-active: rgba(var(--color-blue), 0.12);
--cascader-menu-option-color-active: var(--color-secondary);
--cascader-menu-option-fill-active: rgba(var(--color-secondary), 0.12);
--cascader-menu-option-color-hover: var(--font-color-base);
--cascader-menu-option-fill-hover: rgba(var(--color-black), 0.06);
--cascader-menu-option-color-disabled: #999;
@ -301,15 +309,14 @@
-------------------------- */
--tab-font-size: var(--font-size-base);
--tab-border-line: 1px solid #e4e4e4;
--tab-header-color-active: var(--color-blue);
--tab-header-color-active: var(--color-secondary);
--tab-header-color-hover: var(--font-color-base);
--tab-header-color: var(--font-color-base);
--tab-header-fill-active: rgba(var(--color-black), 0.06);
--tab-header-fill-hover: rgba(var(--color-black), 0.06);
--tab-vertical-header-width: 90px;
--tab-vertical-header-count-color: var(--color-white);
--tab-vertical-header-count-fill: var(--color-blue);
--tab-horizontal-border: 2px solid #438de0;
--tab-vertical-header-count-fill: var(--color-secondary);
/* Button
-------------------------- */
@ -331,7 +338,7 @@
--button-mini-padding-vertical: 4px;
--button-mini-padding-horizontal: 4px;
--button-default-color: #1F2D3D;
--button-default-color: var(--color-base-black);
--button-default-fill: var(--color-white);
--button-default-border: #c4c4c4;
@ -339,8 +346,8 @@
--button-ghost-fill: transparent;
--button-ghost-border: none;
--button-disabled-color: var(--color-grey);
--button-disabled-fill: #EFF2F7;
--button-disabled-color: var(--color-extra-light-silver);
--button-disabled-fill: var(--color-extra-light-gray);
--button-disabled-border: var(--disabled-border-base);
--button-primary-border: var(--color-primary);
@ -374,9 +381,9 @@
/* Switch
-------------------------- */
--switch-on-color: var(--color-primary);
--switch-off-color: var(--color-grey);
--switch-disabled-color: #E5E9F3;
--switch-disabled-text-color: #F9FAFC;
--switch-off-color: var(--color-extra-light-silver);
--switch-disabled-color: var(--color-light-gray);
--switch-disabled-text-color: var(--color-dark-white);
--switch-font-size: var(--font-size-base);
--switch-core-border-radius: 12px;
@ -386,22 +393,21 @@
/* Dialog
-------------------------- */
--dialog-background-color: var(--color-blue);
--dialog-footer-background: var(--color-blue-lighter);
--dialog-background-color: var(--color-secondary);
--dialog-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
--dialog-tiny-width: 30%;
--dialog-small-width: 50%;
--dialog-large-width: 90%;
--dialog-close-color: var(--color-grey);
--dialog-close-color: var(--color-extra-light-silver);
--dialog-close-hover-color: var(--color-primary);
--dialog-title-font-size: 16px;
--dialog-font-size: 14px;
/* Table
-------------------------- */
--table-border-color: #e0e6ed;
--table-text-color: #1f2d3d;
--table-header-background: #EFF2F7;
--table-border-color: color(var(--border-color-base) h(-3) s(27%) l(90%));
--table-text-color: var(--color-base-black);
--table-header-background: var(--color-extra-light-gray);
/* Pagination
-------------------------- */
@ -409,7 +415,7 @@
--pagination-fill: var(--color-white);
--pagination-color: var(--link-color);
--pagination-border-radius: 2px;
--pagination-button-color: #99a9bf;
--pagination-button-color: var(--color-light-silver);
--pagination-button-size: 28px;
--pagination-button-disabled-color: #e4e4e4;
--pagination-button-disabled-fill: var(--color-white);
@ -425,14 +431,14 @@
--popover-arrow-size: 6px;
--popover-padding: 10px;
--popover-title-font-size: 13px;
--popover-title-color: #1f2d3d;
--popover-title-color: var(--color-base-black);
/* Tooltip
-------------------------- */
--tooltip-fill: #1f2d3d;
--tooltip-fill: var(--color-base-black);
--tooltip-color: var(--color-white);
--tooltip-font-size: 12px;
--tooltip-border-color: #1f2d3d;
--tooltip-border-color: var(--color-base-black);
--tooltip-arrow-size: 6px;
--tooltip-padding: 10px;
@ -445,8 +451,8 @@
--tag-font-size: 12px;
--tag-border-radius: 4px;
--tag-gray-fill: #e5e9f2;
--tag-gray-border: #e5e9f2;
--tag-gray-fill: var(--color-light-gray);
--tag-gray-border: var(--color-light-gray);
--tag-gray-color: var(--link-color);
--tag-primary-fill: rgba(32,159,255,0.10);
@ -468,7 +474,7 @@
/* Dropdown
-------------------------- */
--dropdown-menu-box-shadow: var(--box-shadow-dark);
--dropdown-menuItem-hover-fill: #e5e9f2;
--dropdown-menuItem-hover-fill: var(--color-light-gray);
--dropdown-menuItem-hover-color: var(--link-color);
/* Badge
@ -488,10 +494,10 @@
/* Slider
--------------------------*/
--slider-main-background-color: var(--color-primary);
--slider-runway-background-color: #e5e9f2;
--slider-button-hover-color: #1d8ce0;
--slider-stop-background-color: var(--color-grey);
--slider-disable-color: var(--color-grey);
--slider-runway-background-color: var(--color-light-gray);
--slider-button-hover-color: shade(var(--color-primary), 0.12);
--slider-stop-background-color: var(--color-extra-light-silver);
--slider-disable-color: var(--color-extra-light-silver);
--slider-margin: 16px 0;
--slider-border-radius: 3px;
@ -509,14 +515,14 @@
/* Steps
--------------------------*/
--menu-item-color: var(--link-color);
--menu-item-fill: #eff2f7;
--menu-item-fill: var(--color-extra-light-gray);
--menu-item-hover-fill: var(--disabled-border-base);
--submenu-item-fill: #e5e9f2;
--submenu-item-fill: var(--color-light-gray);
--dark-menu-item-color: var(--link-color);
--dark-menu-item-fill: #324057;
--dark-menu-item-fill: var(--color-light-black);
--dark-menu-item-hover-fill: var(--link-color);
--dark-submenu-item-fill: #1f2d3d;
--dark-submenu-item-fill: var(--color-base-black);
/* Rate
--------------------------*/
@ -524,19 +530,19 @@
--rate-font-size: var(--font-size-base);
--rate-icon-size: 18px;
--rate-icon-margin: 6px;
--rate-icon-color: #C6D1DE;
--rate-icon-color: var(--color-extra-light-silver);
/* DatePicker
--------------------------*/
--datepicker-color: var(--link-color);
--datepicker-off-color: #ddd;
--datepicker-header-color: var(--border-color-hover);
--datepicker-icon-color: #99a9bf;
--datepicker-icon-color: var(--color-light-silver);
--datepicker-border-color: var(--disabled-border-base);
--datepicker-inner-border-color: #e4e4e4;
--datepicker-cell-hover-color: #e5e9f2;
--datepicker-inrange-color: #D3ECFF;
--datepicker-inrange-hover-color: #AFDCFF;
--datepicker-cell-hover-color: var(--color-light-gray);
--datepicker-inrange-color: tint(var(--color-primary), 0.8);
--datepicker-inrange-hover-color: tint(var(--color-primary), 0.64);
--datepicker-active-color: var(--color-primary);
--datepicker-text-hover-color: var(--color-primary);
@ -547,8 +553,8 @@
/* Scrollbar
--------------------------*/
--scrollbar-background-color: rgba(#99a9bf, .3);
--scrollbar-hover-background-color: rgba(#99a9bf, .5);
--scrollbar-background-color: rgba(var(--color-light-silver), .3);
--scrollbar-hover-background-color: rgba(var(--color-light-silver), .5);
/* Carousel
--------------------------*/
@ -564,14 +570,14 @@
/* Collapse
--------------------------*/
--collapse-border-color: #e0e6ed;
--collapse-border-color: color(var(--border-color-base) h(-3) s(27%) l(90%));
--collapse-header-height: 43px;
--collapse-border-radius: 0;
--collapse-header-padding: 20px;
--collapse-header-fill: #fff;
--collapse-header-color: #475669;
--collapse-header-fill: var(--color-white);
--collapse-header-color: var(--color-extra-light-black);
--collapse-header-size: 13px;
--collapse-content-fill: #f9fafc;
--collapse-content-fill: var(--color-dark-white);
--collapse-content-size: 13px;
--collapse-content-color: #1f2d3d;
--collapse-content-color: var(--color-base-black);
}

View File

@ -31,7 +31,7 @@
&.current .cell {
background-color: var(--datepicker-active-color) !important;
color: #fff;
color: var(--color-white);
}
}
}

View File

@ -5,7 +5,7 @@
color: var(--datepicker-color);
border: 1px solid var(--datepicker-border-color);
box-shadow: 0 2px 6px #ccc;
background: #fff;
background: var(--color-white);
border-radius: 2px;
line-height: 20px;
margin: 5px 0;
@ -27,7 +27,7 @@
border-top: 1px solid var(--datepicker-inner-border-color);
padding: 4px;
text-align: right;
background-color: #fff;
background-color: var(--color-white);
position: relative;
}
@ -103,7 +103,7 @@
border-right: 1px solid var(--datepicker-inner-border-color);
box-sizing: border-box;
padding-top: 6px;
background-color: #f9fafc;
background-color: var(--color-dark-white);
}
.el-picker-panel *[slot=sidebar] + .el-picker-panel__body,

View File

@ -75,7 +75,7 @@
background-color: transparent;
outline: none;
font-size: 12px;
color: #8492a6;
color: var(--color-base-silver);
&.confirm {
font-weight: 800;

View File

@ -35,7 +35,7 @@
&.current .cell {
background-color: var(--datepicker-active-color) !important;
color: #fff;
color: var(--color-white);
}
}
}

View File

@ -8,7 +8,7 @@
position: absolute;
left: 50%;
transform: translateX(-50%);
background: #fff;
background: var(--color-white);
border-radius: var(--border-radius-small);
box-shadow: var(--dialog-box-shadow);
box-sizing: border-box;
@ -55,12 +55,12 @@
line-height: 1;
font-size: var(--dialog-title-font-size);
font-weight: bold;
color: #1f2d3d;
color: var(--color-base-black);
}
@e body {
padding: 30px 20px;
color: #475669;
color: var(--color-extra-light-black);
font-size: var(--dialog-font-size);
}

View File

@ -6,7 +6,7 @@
@b dropdown {
display: inline-block;
position: relative;
color: #475669;
color: var(--color-extra-light-black);
font-size: var(--font-size-base);
.el-button-group {
@ -27,8 +27,8 @@
}
@b dropdown-menu {
margin: 5px 0;
background-color: #fff;
border: 1px solid #D3DCE6;
background-color: var(--color-white);
border: 1px solid var(--color-base-gray);
box-shadow: var(--dropdown-menu-box-shadow);
padding: 6px 0;
z-index: 10;
@ -51,19 +51,19 @@
@m divided {
position: relative;
margin-top: 6px;
border-top: 1px solid #D3DCE6;
border-top: 1px solid var(--color-base-gray);
&:before {
content: '';
height: 6px;
display: block;
margin: 0 -10px;
background-color: #fff;
background-color: var(--color-white);
}
}
@when disabled {
cursor: default;
color: #c0ccda;
color: var(--color-extra-light-silver);
pointer-events: none;
}
}

View File

@ -40,7 +40,7 @@
vertical-align: middle;
float: left;
font-size: 14px;
color: #5e6d82;
color: var(--color-extra-light-black);
line-height: 1;
padding: 11px 12px 11px 0;
box-sizing: border-box;
@ -52,7 +52,7 @@
@utils-clearfix;
}
@e error {
color: #ff4949;
color: var(--color-danger);
font-size: 12px;
line-height: 1;
padding-top: 4px;

View File

@ -20,7 +20,7 @@
line-height: calc(var(--input-height) - 2);
top: 1px;
text-align: center;
color: #99A9BF;
color: var(--color-light-silver);
cursor: pointer;
position: absolute;
z-index: 1;

View File

@ -114,8 +114,8 @@
display: table-cell;
}
@e append, prepend {
background-color: #f9fafc;
color: #99a9bf;
background-color: var(--color-dark-white);
color: var(--color-light-silver);
vertical-align: middle;
display: table-cell;
position: relative;
@ -173,6 +173,7 @@
@b textarea {
display: inline-block;
width: 100%;
vertical-align: bottom;
@e inner {
display: block;
@ -183,7 +184,7 @@
width: 100%;
font-size: var(--font-size-base);
color: var(--input-color);
background-color: #fff;
background-color: var(--color-white);
background-image: none;
border: var(--input-border);
border-radius: 4px;

View File

@ -11,6 +11,7 @@
right: 0;
bottom: 0;
left: 0;
transition: opacity 0.3s;
@when fullscreen {
position: fixed;
@ -54,6 +55,11 @@
}
}
.el-loading-fade-enter,
.el-loading-fade-leave-active {
opacity: 0;
}
@keyframes loading-rotate {
100% {
transform: rotate(360deg);

View File

@ -33,18 +33,18 @@
& .el-menu-item,
& .el-submenu__title {
color: #c0ccda;
color: var(--color-extra-light-silver);
&:hover {
background-color: #475669;
background-color: var(--color-extra-light-black);
}
}
& .el-submenu .el-menu {
background-color: #1f2f3d;
background-color: var(--color-base-black);
& .el-menu-item:hover {
background-color: #475669;
background-color: var(--color-extra-light-black);
}
}
}
@ -59,6 +59,11 @@
box-sizing: border-box;
border-bottom: 5px solid transparent;
a,
a:hover {
color: inherit;
}
&:hover {
background-color: var(--menu-item-hover-fill);
}
@ -71,9 +76,9 @@
position: absolute;
top: 65px;
left: 0;
border:1px solid #d3dce6;
border:1px solid var(--color-base-gray);
padding: 5px 0;
background-color: #fff;
background-color: var(--color-white);
z-index: 100;
min-width: 100%;
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.12), 0px 0px 6px 0px rgba(0,0,0,0.04);
@ -86,7 +91,7 @@
}
& .el-menu-item {
background-color: #fff;
background-color: var(--color-white);
float: none;
height: 36px;
line-height: 36px;
@ -97,7 +102,7 @@
position: static;
vertical-align: middle;
margin-left: 5px;
color: #99a9bf;
color: var(--color-light-silver);
margin-top: -3px;
}
}
@ -120,10 +125,10 @@
& .el-submenu {
.el-menu-item,
.el-submenu-title {
color: #475669;
color: var(--color-extra-light-black);
&:hover {
background-color: #d3dce6;
background-color: var(--color-base-gray);
}
}
.el-menu-item.is-active {
@ -147,7 +152,7 @@
margin-right: 0;
}
&:hover {
background-color: #d3dce6;
background-color: var(--color-base-gray);
}
@when active {
color: var(--color-primary);
@ -160,11 +165,11 @@
@extend menu-item;
&:hover {
background-color: #d3dce6;
background-color: var(--color-base-gray);
}
}
& .el-menu {
background-color: #e5e9f2;
background-color: var(--color-light-gray);
}
& .el-menu-item {
height: 50px;
@ -172,7 +177,7 @@
padding: 0 45px;
&:hover {
background-color: #d3dce6;
background-color: var(--color-base-gray);
}
}
@e icon-arrow {
@ -208,7 +213,7 @@
line-height: normal;
font-size: 14px;
padding-left: 20px;
color: #99a9bf;
color: var(--color-light-silver);
}
}
}

View File

@ -10,7 +10,7 @@
text-align: left;
display: inline-block;
vertical-align: middle;
background-color: #fff;
background-color: var(--color-white);
width: var(--msgbox-width);
border-radius: var(--msgbox-border-radius);
font-size: var(--msgbox-font-size);

View File

@ -13,7 +13,7 @@
left: 50%;
top: 20px;
transform: translateX(-50%);
background-color: #fff;
background-color: var(--color-white);
transition: opacity 0.3s, transform .4s;
overflow: hidden;

View File

@ -30,13 +30,13 @@
&:hover,
&:focus {
background: #fff;
background: var(--color-white);
border-color: $border-color;
color: $background-color;
}
&:active {
background: #fff;
background: var(--color-white);
border-color: shade($border-color, var(--button-active-shade-percent));
color: shade($background-color, var(--button-active-shade-percent));
outline: none;

View File

@ -10,7 +10,7 @@
border-radius: var(--border-radius-small);
position: fixed;
right: 16px;
background-color: #fff;
background-color: var(--color-white);
box-shadow: var(--notification-shadow);
transition: opacity 0.3s, transform .3s, right .3s, top 0.4s;
overflow: hidden;
@ -20,18 +20,20 @@
@when with-icon {
margin-left: 55px;
}
& span {
font-size: var(--notification-title-font-size);
color: var(--notification-title-color);
}
}
& p {
font-size: var(--notification-font-size);
line-height: 21px;
margin: 10px 0 0 0;
color: var(--notification-color);
text-align: justify;
}
@e title {
font-weight: normal;
font-size: var(--notification-title-font-size);
color: var(--notification-title-color);
}
@e content {
font-size: var(--notification-font-size);
line-height: 21px;
margin: 10px 0 0 0;
color: var(--notification-color);
text-align: justify;
}
@e icon {

View File

@ -152,6 +152,7 @@
vertical-align: top;
font-size: 0;
padding: 0;
margin: 0;
li {
padding: 0 4px;
@ -167,6 +168,7 @@
cursor: pointer;
box-sizing: border-box;
text-align: center;
margin: 0;
&:last-child {
border-right: 1px solid var(--pagination-border-color);

View File

@ -8,7 +8,7 @@
@e text {
font-size:14px;
color:#475669;
color:var(--color-extra-light-black);
display: inline-block;
vertical-align: middle;
margin-left: 10px;
@ -81,7 +81,7 @@
@e outer {
height: 6px;
border-radius: 100px;
background-color: #e5e9f2;
background-color: var(--color-light-gray);
overflow: hidden;
position: relative;
vertical-align: middle;
@ -102,7 +102,7 @@
@e innerText {
display: inline-block;
vertical-align: middle;
color: #fff;
color: var(--color-white);
font-size: 12px;
margin: 0 5px;
}

Some files were not shown because too many files have changed in this diff Show More