Compare commits

...

53 Commits

Author SHA1 Message Date
Leopoldthecoder
7d7d5a8757 [release] 2.0.2 2017-10-31 18:48:53 +08:00
Leopoldthecoder
906580eb88 [build] 2.0.2 2017-10-31 18:48:53 +08:00
Leopoldthecoder
c1155b3be0 Table: avoid doLayout continuous executing 2017-10-31 18:46:35 +08:00
Leopoldthecoder
80e60efc0a Changelog: update for 2.0.2 2017-10-31 18:46:35 +08:00
Leopoldthecoder
6dc98ebcf7 Select: fix menu not expand when clicked on input 2017-10-31 18:46:35 +08:00
Leopoldthecoder
9ae38e01e4 Pagination: fix jumper height in specified sizes 2017-10-31 18:46:35 +08:00
Leopoldthecoder
ee72cd5b9f Tree: expand hot area of arrow icon 2017-10-31 17:09:48 +08:00
Leopoldthecoder
1412b5757c Step: fix icon style 2017-10-31 17:09:48 +08:00
Leopoldthecoder
633cb30d52 Loading: use class to set styles 2017-10-31 17:09:48 +08:00
Leopoldthecoder
03a52ab38e Table: update sort-by docs 2017-10-31 17:09:48 +08:00
胡明昊
fecc38f495 DatePicker: fix bug for wrong year number when week cross the year like 2014/12/29 2017-10-31 14:24:10 +08:00
Leopoldthecoder
5d172ad5cf Select: fix input height of mini size 2017-10-31 11:36:09 +08:00
wangfengming
877718099e Table: support sort-by. can't sort if sort-by is null 2017-10-31 11:35:40 +08:00
wangfengming
f642294949 Table: support sort-by, use isArray to test sortBy 2017-10-31 11:35:40 +08:00
wangfengming
0a24f05125 Table: support sort-by, use isArray to test sortBy 2017-10-31 11:35:40 +08:00
wangfengming
7074a247f4 Table: support sort-by 2017-10-31 11:35:40 +08:00
XpLoDWilD
6619daf1ab Var: Allow transitions to be overridden
This allows to override transitions parameters (for example if you want them slower or faster) the same way you would tweak the primary/accent colors.
2017-10-31 10:16:43 +08:00
Leopoldthecoder
5d6a7b6f9c Upload: fix icons in list type 2017-10-31 10:09:17 +08:00
Leopoldthecoder
0cca820dac Tree: reserve node expanding state while filtering 2017-10-30 06:22:48 -05:00
linzer
3eb06dcb0e input-number allow input '.' '-' 2017-10-30 05:25:06 -05:00
Leopoldthecoder
409a3c852f Form: fix validate state 2017-10-30 04:03:19 -05:00
Leopoldthecoder
146e02c4a3 DatePicker: workaround for Chromium 55 - 57 2017-10-30 04:03:19 -05:00
Allenice
468124f956 Form: fix async validate bug 2017-10-30 01:51:14 -05:00
Allenice
476d1c4f6e Form: fix async validate bug 2017-10-30 01:51:14 -05:00
Leopoldthecoder
0c47e6d308 RepeatClick: ignore right button down 2017-10-28 21:47:41 -05:00
Leopoldthecoder
85a8ea0ade Checkbox: fix change event param 2017-10-28 06:05:43 -05:00
Leopoldthecoder
2b5efef3fa [release] 2.0.1 2017-10-28 17:13:25 +08:00
Leopoldthecoder
c0e9a0f44f [build] 2.0.1 2017-10-28 17:13:24 +08:00
Leopoldthecoder
31e39a3e8a Changelog: update for 2.0.1 2017-10-28 04:10:54 -05:00
Leopoldthecoder
8479b2fbaf bug fixes 2017-10-28 03:10:52 -05:00
Leopoldthecoder
2e8161e68e Fix checkbox-button and radio-button gap 2017-10-27 04:41:27 -05:00
Axel Manuel
cdf05c46ec Tree: remove undefined member 2017-10-27 02:53:28 -05:00
Axel Manuel
d180ec5c9e Carbon: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
6a172c758b MessageBox: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
c3d996a60d Loading: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
aa709c7071 Message: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
e8cf84cbc0 Notification: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
9aac9d80eb Tree: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Axel Manuel
ca0bc1359f Carousel: Remove implicit any from .d.ts 2017-10-27 02:53:28 -05:00
Leopoldthecoder
407fd70ba6 [release] 2.0.0 2017-10-27 11:56:27 +08:00
Leopoldthecoder
6995641d72 [build] 2.0.0 2017-10-27 11:56:27 +08:00
Leopoldthecoder
f3aa9b30ad Changelog: update for 2.0.0 2017-10-26 22:42:55 -05:00
Leopoldthecoder
d2efebcbeb fix getPropByPath error 2017-10-26 22:29:22 -05:00
杨奕
4b3edc13ab Merge pull request #7750 from ElemeFE/carbon
Carbon
2017-10-26 01:05:33 -05:00
Leopoldthecoder
3cc8b0064b Merge remote-tracking branch 'eleme/dev' into carbon 2017-10-26 13:57:06 +08:00
Leopoldthecoder
cee3154304 update release scripts 2017-10-26 00:25:24 -05:00
wacky6.AriesMBP
07acf66a69 picker: fix clear value 2017-10-25 23:48:47 -05:00
Leopoldthecoder
4aff63826c misc updates 2017-10-25 23:01:23 -05:00
Leopoldthecoder
00e8c7454f misc updates and fixes 2017-10-25 22:21:35 -05:00
wacky6.AriesMBP
b85b67d928 test: add change event test for input-number 2017-10-25 22:11:08 -05:00
John Heiner
e2932fd781 date-picker: added name attr support 2017-10-25 21:52:26 -05:00
Chris Anderson
d2908487d7 Fixes #7728 2017-10-25 21:50:16 -05:00
wacky6.AriesMBP
c856d9268b date-picker: support array for name attr 2017-10-25 21:48:55 -05:00
88 changed files with 998 additions and 961 deletions

View File

@@ -1,15 +1,121 @@
## Changelog
### 2.0.0-rc.1
### 2.0.2
*2017-10-25*
*2017-10-31*
- Now right-clicking the buttons of InputNumber won't change its value, #7817
- `validate` method of Form can now wait for asynchronous validations before executing its callback, #7774 (by @Allenice)
- Fixed range selection of DatePicker not working in Chromium 53-57 browsers, #7838
- Fixed missing preview and delete icons of Upload when its `list-type` is picture-card, #7857
- Added `sort-by` attribute for TableColumn, #7828 (by @wangfengming)
- Fixed DatePicker sometimes displaying wrong year number when selecting the first week in week mode, #7860 (by @hh23485)
- Fixed icon style error of vertical Steps, #7891
- The hot area for node arrows in Tree is expanded, #7891
### 2.0.1
*2017-10-28*
- Fixed style error of RadioButton and CheckboxButton, #7793
- Fixed TimePicker not respond to mouse scroll in some conditions, #7811
- Fixed incomplete styles of some components when imported on demand, #7811
### 2.0.0 Carbon
*2017-10-27*
#### New features
- Form
- Added `clearValidate` method for clearing validating results for all form items, #7623
- General
- A new theme: `theme-chalk`
- Accessibility of the following components are improved: Alert, AutoComplete, Breadcrumb, Button, Checkbox, Collapse, Input, InputNumber, Menu, Progress, Radio, Rate, Slider, Switch, Upload
- Added TypeScript typings
- All existing icons are redesigned. Some new icons are added
- Added a series of breakpoint-based utility classes that hide elements when the viewport size meets certain conditions
- Added layout components: Container, Header, Aside, Main, Footer
- Now you can configure component sizes globally. When importing Element, you can add a global config object with a `size` prop to configure default sizes for all components.
- Button
- Added `round` attribute. It's used for round-cornered Buttons #6643
- TimeSelect
- Now can be navigated by `Up` and `Down`, and hitting `Enter` selects the time #6023
- TimePicker
- Now can be navigated by arrow keys, and hitting `Enter` selects the time #6050
- Added `start-placeholder` and `end-placeholder`. They're placeholders for the two input boxes in range mode #7169
- Added `arrow-control` attribute to spin the time with arrows #7438
- Tree
- Now child nodes don't render before the first expand #6257
- Added `check-descendants` attribute. It determines if child nodes are checked when checking their parent node in `lazy` mode #6235
- Tag
- Added `size` attribute #7203
- Datepicker
- Now `timeFormat` can format the TimePicker when type is set to `datetimerange` #6052
- Added `start-placeholder` and `end-placeholder`. They're placeholders for the two input boxes in range mode #7169
- Added `value-format` attribute to customize the format of the binding value, #7367
- Added `unlink-panels` attribute to unlink the two date panels when selecting a date range
- MessageBox
- Added `closeOnHashChange` attribute #6043
- Added `center` attribute so that the content can be centered #7029
- Added `roundButton` attribute to display round Buttons #7029
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6043
- Added `inputType` attribute to assign type for the inner input box, #7651
- Dialog
- Added `width``fullscreen``append-to-body` attributes. Now Dialog can be nested
- Added `center` attribute so that the content can be centered #7042
- Added `focus-after-closed``focus-after-open` to improve accessibility #6511
- ColorPicker
- Now you can type colors in the input box #6167
- Added `size` and `disabled` attributes #7026
- Added `popper-class` attribute #7351
- Message
- Now color of the icons can be overridden by CSS #6207
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6207
- Added `center` attribute so that the content can be centered #6875
- Notification
- Added `position` attribute to configure where Notification pops up #6231
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6231
- Added `showClose` attribute to hide the close button #6402
- Rate
- Added `show-score` attribute to determine if current score is displayed #6295
- Tabs
- Added `tab-position` attribute #6096
- Radio
- Added `border` and `size` attributes #6690
- Checkbox
- Added `border` and `size` attributes #6690
- Alert
- Added `center` attribute so that the content can be centered #6876
- Menu
- Added `background-color`, `text-color` and `active-text-color` attributes #7064
- Added `open` and `close` methods to open and close SubMenu programmatically, #7412
- Form
- Added `inline-message` attribute to determine if the validation message is displayed in inline style #7032
- Added `status-icon` attribute to display a feedback icon when validated #7032
- Form and FormItem now have a `size` attribute. Inner components will inherit this size if not specified on themselves, #7428
- `validate` method will now return a promise if the callback is omitted, #7405
- Added `clearValidate` method for clearing validating results for all form items, #7623
- Input
- Added `suffix` and `prefix` named slots, `suffixIcon` and `prefixIcon` attributes to add contents inside the input box #7032
- Breadcrumb
- Added `separator-class` attribute to support icons as item separators #7203
- Steps
- Added `simple` attribute to activate simple-styled Steps #7274
- Pagination
- Added `prev-text` and `next-text` attributes to customize texts of previous page and next page #7005
- Loading
- Now you can customize spinner icon and background color with `spinner` and `background` prop, #7390
- Autocomplete
- Added `debounce` attribute, #7413
- Upload
- Added `limit` and `on-exceed` attributes to limit the amount of files, #7405
- DateTimePicker
- Added `time-arrow-control` attribute to activate `arrow-control` of the nesting TimePicker, #7438
- Layout
- Added a new breakpoint `xl` for viewport wider than 1920px
- Table
- Added `span-method` attribute for merging cells
- Added `clearSort` method to clear sorting programmatically
- Added `clearFilter` method to clear filter programmatically
- For expandable rows, when a row is expanded, a `.expanded` class will be added to its class list, so that you can customize its style
- Added `size` attribute
- Added `toggleRowExpansion` method to expand or collapse expandable rows programmatically
- Added `cell-class-name` attribute to assign class name for cells
@@ -20,237 +126,74 @@
- Added `header-cell-style` attribute to style header cells
- TableColumn's `prop` attribute now accepts `object[key]` notations
- Added `index` attribute for TableColumn to customize row indices
#### Fixes
- Table
- Fixed a dynamic `max-height` bug
- Fixed some style calculation errors
#### Breaking changes
- Autocomplete
- Removed `props` attribute. Now you can use `value-key` attribute to designate key name of the input suggestion
object for display
- Table
- `append` slot is moved outside the `tbody` element to avoid multiple rendering
- `expand` event is renamed to `expand-change`
- The params of `row-class-name` and `row-style` method is now an object
### 2.0.0-beta.1
*2017-10-20*
#### New features
- General
- Added TypeScript typings
- All existing icons are redesigned. Some new icons are added.
- To help you migrate from Element 1.x, we added some console warnings against deprecated APIs. When you use a removed or renamed attribute or event in your project, you'll get a warning like this:
```
[Element Migrating][ElSwitch][Attribute]: on-color is renamed to active-color.
```
- Added a series of breakpoint-based utility classes that hide elements when the viewport size meets certain conditions
- Layout
- Added a new breakpoint `xl` for viewport wider than 1920px
- Table
- Added `span-method` attribute for merging cells
- Added `clearSort` method to clear sorting programmatically
- Added `clearFilter` method to clear filter programmatically
- For expandable rows, when a row is expanded, a `.expanded` class will be added to its class list, so that you can customize its styles
- DatePicker
- Added `unlink-panels` attribute to unlink the two date panels when selecting a date range
- Select
- Added `reserve-keyword` attribute for reserving current search keyword after selecting an option
#### Fixes
#### Bug fixes
- DatePicker
- Fixed `v-model` returning the second day of the selected week in week mode #6038
- Fixed the first input being cleared in `daterange` type #6021
- DateTimePicker
- Fixed DateTimePicker and TimePicker affecting each other when picked #6090
- Fixed hour and second can be beyond limit when selecting time #6076
- TimePicker
- Fixed `v-model` not update correctly when blurred #6023
- Dialog
- Fixed texts having blurry edges when opening and closing nesting dropdowns #6088
- Select
- Improved performance. Now Vue dev-tool won't crash when a large number of Selects are destroyed #6151
- Table
- Now `header-align` of TableColumn works properly
- Fixed a bug that Table remains hiding when its parent element appears from `display: none`
- Fixed Table expanding its width when its parent element has `display: flex`
- Fixed a bug that fixed columns of a Table with `append` slot would disappear when data is dynamically fetched
- Fixed `expand-row-keys` attribute not working with initial value
- Fixed filter failing when `data` updates
- Fixed a calculation error of fixed columns layout with grouped headers
- Fixed a dynamic `max-height` bug
- Fixed some style calculation errors
#### Breaking changes
- General
- Removed `theme-default`
- Compatible with Vue 2.5.2+ and IE 10+
- `change` event of form components and `current-change` event of Pagination now only trigger on user interaction
- `size` attribute of Button and form components now accept `medium`, `small` and `mini`
- To facilitate the use of third-party icons, `icon` attribute of Button and Steps, `prefix-icon` and `suffix-icon` attributes of Input now require a full class name
- Dialog
- Removed `size` attribute. Now the size of Dialog can be configured by `width` and `fullscreen`
- Now the visibility of Dialog cannot be controlled by `v-model`
- Rate
- `text-template` is renamed to `score-template`
- Dropdown
- `menu-align` is renamed to `placement`. Now it supports more positions
- Transfer
- `footer-format` is renamed to `format`
- Switch
- Attributes starting with `on-*` will be parsed to events in JSX, making all `on-*` attributes of Switch not
able to work in JSX. So `on-*` attributes are renamed to `active-*`, and accordingly `off-*` attributes are renamed to `inactive-*`. This change affects the following attributes: `on-icon-class`, `off-icon-class`, `on-text`, `off-text`, `on-color`, `off-color`, `on-value`, `off-value`
able to work in JSX. So `on-*` attributes are renamed to `active-*`, and accordingly `off-*` attributes are renamed to `inactive-*`. This change affects the following attributes: `on-icon-class`, `off-icon-class`, `on-text`, `off-text`, `on-color`, `off-color`, `on-value`, `off-value`
- `active-text` and `inactive-text` attributes now don't have default values
- Tag
- `type` attribute now accepts `success`, `info`, `warning` and `danger`
- Menu
- Removed `theme` attribute. The color of Menu can be configured using `background-color`, `text-color` and `active-text-color`
- Input
- Removed `icon` attribute. Now the suffix icon can be configured using `suffix-icon` attribute or `suffix` named slot
- Removed `on-icon-click` attribute and `click` event. Now to add click handler on icons, please use named slots
- `change` event now behaves like the native input element, which triggers only on blur or pressing enter. If you need to respond to user input in real time, you can use `input` event.
- Autocomplete
- Removed `custom-item` attribute. Now the template of input suggestions can be customized using `scoped slot`
- Removed `props` attribute. Now you can use `value-key` attribute to designate key name of the input suggestion object for display
- Steps
- Removed `center` attribute
- Now the Steps will fill its parent container by default
- DatePicker
- The params of DatePicker's `change` event is now the binding value itself. Its format is controlled by `value-format`
- Table
- Removed support for customizing column template using `inline-template`
- `sort-method` now aligns with `Array.sort`. It should return a number instead of a boolean
### 2.0.0-alpha.3
*2017-10-16*
#### New features
- General
- Configure component sizes globally. Now when you import Element, you can add a global config object with a `size` prop to configure default sizes for all components. For fully import:
```JS
import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element, { size: 'small' })
```
For partial import:
```JS
import Vue from 'vue'
import { Button } from 'element-ui'
Vue.prototype.$ELEMENT = { size: 'small' }
Vue.use(Button)
```
With the above config, the default size of all components that have `size` attribute will be 'small'.
- Loading
- Now you can customize spinner icon and background color with `spinner` and `background` prop, #7390
- Autocomplete
- Added `debounce` attribute, #7413
- Upload
- Added `limit` and `on-exceed` attributes to limit the amount of files, #7405
- Menu
- Added `open` and `close` methods to open and close SubMenu programmatically, #7412
- DatePicker
- Added `value-format` attribute to customize the format of the binding value, #7367
- TimePicker
- Added `arrow-control` attribute to spin the time with arrows #7438
- DateTimePicker
- Added `time-arrow-control` attribute to activate `arrow-control` of the nesting TimePicker, #7438
- Form
- Form and Form-item now have a `size` attribute. Inner components will inherit this size if not specified on themselves, #7428
- `validate` method will now return a promise if the callback is omitted, #7405
#### Fixes
- Fixed the console warning `Injection "elFormItem" not found` of some components
#### Breaking changes
- The params of DatePicker's `change` event is now the binding value itself. Its format is controlled by `value-format`
- Input's `change` event now behaves like the native input element, which triggers only on blur or pressing enter. If you need to respond to user input in real time, you can use `input` event.
- Only compatible with Vue 2.5.2 and beyond
### 2.0.0-alpha.2
*2017-10-05*
- Updated the primary color of `theme-chalk`, #7351
- Fixed console error when using Dropdown, #7322
- Fixed console error when using Menu, #7321
- Added `popper-class` attribute for ColorPicker, #7351
- Now Button's `disabled` attribute works correctly, #7352
### 2.0.0-alpha.1
*2017-09-30*
#### New features
- General
- A new theme: `theme-chalk`
- Accessibility of the following components are improved: Alert, AutoComplete, Breadcrumb, Button, Checkbox, Collapse, Input, InputNumber, Menu, Progress, Radio, Rate, Slider, Switch, Upload
- Layout components: Container, Header, Aside, Main, Footer
- Button
- Added `round` attribute. It's used for round-cornered Buttons #6643
- TimeSelect
- Now can be navigated by `Up` and `Down`, and hitting `Enter` selects the time #6023
- TimePicker
- Now can be navigated by arrow keys, and hitting `Enter` selects the time #6050
- Added `start-placeholder` and `end-placeholder`. They're placeholders for the two input boxes in range mode #7169
- Tree
- Now child nodes don't render before the first expand #6257
- Added `check-descendants` attribute. It determines if child nodes are checked when checking their parent node
in `lazy` mode #6235
- Tag
- Added `size` attribute #7203
- Datepicker
- Now `timeFormat` can format the TimePicker when type is set to `datetimerange` #6052
- Added `start-placeholder` and `end-placeholder`. They're placeholders for the two input boxes in range mode #7169
- MessageBox
- Added `closeOnHashChange` attribute #6043
- Added `center` attribute so that the content can be centered #7029
- Added `roundButton` attribute to display round Buttons #7029
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6043
- Dialog
- Added `width`、`fullscreen`、`append-to-body` attributes. Now Dialog can be nested
- Added `center` attribute so that the content can be centered #7042
- Added `focus-after-closed`、`focus-after-open` to improve accessibility #6511
- ColorPicker
- Now you can type colors in the input box #6167
- Added `size` and `disabled` attributes #7026
- Message
- Now color of the icons can be overridden by CSS #6207
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6207
- Added `center` attribute so that the content can be centered #6875
- Notification
- Added `position` attribute to configure where Notification pops up #6231
- Added `dangerouslyUseHTMLString` attribute. When set to `true`, `message` will be parsed as HTML string<sup>*</sup> #6231
- Added `showClose` attribute to hide the close button #6402
- Rate
- Added `show-score` attribute to determine if current score is displayed #6295
- Tabs
- Added `tab-position` attribute #6096
- Radio
- Improved accessibility #6101
- Added `border` and `size` attributes #6690
- Checkbox
- Added `border` and `size` attributes #6690
- Alert
- Added `center` attribute so that the content can be centered #6876
- Menu
- Added `background-color`, `text-color` and `active-text-color` attributes #7064
- Form
- Added `inline-message` attribute to determine if the validation message is displayed in inline style #7032
- Added `status-icon` attribute to display a feedback icon when validated #7032
- Input
- Added `suffix` and `prefix` named slots, `suffixIcon` and `prefixIcon` attributes to add contents inside the input box #7032
- Breadcrumb
- Added `separator-class` attribute to support icons as item separators #7203
- Steps
- Added `simple` attribute to activate simple-styled Steps #7274
- Pagination
- Added `prev-text` and `next-text` attributes to customize texts of prev page and next page #7005
#### Bug fixes
- DatePicker
- Fixed `v-model` returning the second day of the selected week in week mode #6038
- Fixed the first input being cleared in `daterange` type #6021
- DateTimePicker
- Fixed DateTimePicker and TimePicker affecting each other when picked #6090
- Fixed hour and second can be beyond limit when selecting time #6076
- TimePicker
- Fixed `v-model` not update correctly when blurred #6023
- Dialog
- Fixed texts having blurry edges when opening and closing nesting dropdowns #6088
- Select
- Improved performance. Now Vue dev-tool won't crash when a large number of Selects are destroyed #6151
#### Breaking changes
- General
- Removed `theme-default`
- `change` event of form components and `current-change` event of Pagination now only trigger on user interaction
- `size` attribute of Button and form components can no longer be set to `large`. Now they accept `medium`, `small` and `mini`
- To facilitate the use of third-party icons, `icon` attribute of Button and Steps, `prefix-icon` and `suffix-icon` attributes of Input now require a full class name
- Dialog
- Removed `size` attribute. Now the size of Dialog can be configured by `width` and `fullscreen`
- Now the visibility of Dialog cannot be controlled by `v-model`
- Rate
- `text-template` is renamed to `score-template`
- Dropdown
- `menu-align` is renamed to `placement`. Now it supports more positions
- Transfer
- `footer-format` is renamed to `format`
- Switch
- `on-text` and `off-text` attributes now don't have default values
- Tag
- `type` attribute now accepts `success`, `info`, `warning` and `danger`
- `close-transition` is renamed to `disable-transitions`
- Menu
- Removed `theme` attribute. The color of Menu can be configured using `background-color`, `text-color` and `active-text-color`
- Input
- Removed `icon` attribute. Now the suffix icon can be configured using `suffix-icon` attribute or `suffix` named slot
- Removed `on-icon-click` attribute and `click` event. Now to add click handler on icons, please use named slots
- Autocomplete
- Removed `icon` and `on-icon-click` attributes. Now the icons can be configured using `prefix` or `suffix` named slot
- Removed `custom-item` attribute. Now the template of input suggestions can be customized using `scoped slot`
- Table
- Removed support for customizing column template using `inline-template`
- Steps
- Removed `center` attribute
- Now the Steps will fill its parent container by default
- `append` slot is moved outside the `tbody` element to avoid multiple rendering
- `expand` event is renamed to `expand-change`
- The params of `row-class-name` and `row-style` method is now an object
##
<i><sup>*</sup> Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to [XSS attacks](https://en.wikipedia.org/wiki/Cross-site_scripting). So when `dangerouslyUseHTMLString` is on, please make sure the content of `message` is trusted, and **never** assign `message` to user-provided content.</i>

View File

@@ -1,140 +1,39 @@
## 更新日志
### 2.0.0-rc.1
*2017-10-25*
### 2.0.2
#### 新特性
- Form
- 新增 `clearValidate` 方法,用于清空所有表单项的验证信息,#7623
- MessageBox
- 新增 `inputType` 属性,用户指定内部输入框的类型,#7651
- Table
- 新增 `size` 属性,用于控制表格尺寸
- 新增 `toggleRowExpansion` 方法,用于手动展开或关闭行
- 新增 `cell-class-name` 属性,用于指定单元格的类名
- 新增 `cell-style` 属性,用于指定单元格的样式
- 新增 `header-row-class-name` 属性,用于指定表头行的类名
- 新增 `header-row-style` 属性,用于指定表头行的样式
- 新增 `header-cell-class-name` 属性,用于指定表头单元格的类名
- 新增 `header-cell-style` 属性,用于指定表头单元格的样式
- TableColumn 的 `prop` 属性支持 `object[key]` 格式
- TableColumn 新增 `index` 属性,用于自定义索引值
*2017-10-31*
#### 修复
- Table
- 修复 `max-height` 变更后无法恢复的问题
- 修复一些样式上的计算错误
- 在 InputNumber 的加减按钮上单击鼠标右键不再触发值的改变,#7817
- Form 的 `validate` 方法现在能够正确地在异步校验完成后执行回调了,#7774by @Allenice
- 修复 DatePicker 的范围选择在内核为 Chromium 53-57 的浏览器中无法使用的问题,#7838
- 修复 `list-type` 为 picture-card 的 Upload 预览和删除图标丢失的问题,#7857
- 新增 TableColumn 的 `sort-by` 属性,#7828by @wangfengming
- 修复周模式下的 DatePicker 在选择某年第一周可能会显示为前一年第一周的问题,#7860by @hh23485
- 修复垂直模式的 Steps 中图标宽度的样式错误,#7891
- 增大了 Tree 中展开箭头的点击热区,#7891
#### 非兼容性更新
- Autocomplete
- 移除 `props` 属性,现在使用 `value-key` 属性指定输入建议对象中用于显示的键名
- Table
-`append` slot 移至 `tbody` 元素以外,以保证其只被渲染一次
- `expand` 事件更名为 `expand-change`,以保证 API 的命名一致性
- `row-class-name``row-style` 的函数参数改为对象,以保证 API 的一致性
### 2.0.1
### 2.0.0-beta.1
*2017-10-20*
*2017-10-28*
#### 新特性
- 综合
- 新增 TypeScript 类型声明
- 重绘了全部图标,并新增了部分图标
- 为部分非兼容性更新增加控制台警告,方便迁移项目。当你在项目中使用了被移除或更名了的属性或事件时,控制台会出现一条警告,例如:
```
[Element Migrating][ElSwitch][Attribute]: on-color is renamed to active-color.
```
- 新增了一系列基于断点的工具类,用于当视口尺寸满足一定条件时隐藏元素
- Layout
- 新增断点 `xl`,适用于宽度大于 1920px 的视口
- Table
- 新增 `span-method` 属性,用于合并行或列
- 新增 `clearSort` 方法,用于清空排序状态
- 新增 `clearFilter` 方法,用于清空过滤状态
- 对于可展开行,当该行展开时会获得一个 `.expanded` 类名,方便自定义样式
- DatePicker
- 新增 `unlink-panels` 属性,用于在选择日期范围时取消两个日期面板之间的联动
- Select
- 新增 `reserve-keyword` 属性,用于在选择某个选项后保留当前的搜索关键词
- 修复 RadioButton 和 CheckboxButton 的样式问题,#7793
- 修复 TimePicker 在某些情况下无法滚动的问题,#7811
- 修复部分组件在按需引入时样式不完整的问题,#7811
#### 修复
- Table
- 修复 TableColumn 的 `header-align` 属性失效的问题
- 修复 Table 在父元素从 `display: none` 变成其他状态时会隐藏的问题
- 修复 Table 在父元素为 `display: flex` 时可能出现的宽度逐渐变大的问题
- 修复 `append` 具名 slot 和固定列并存时,动态获取表格数据会导致固定列消失的问题
- 修复 `expand-row-keys` 属性初始化无效的问题
- 修复 `data` 改变时过滤条件失效的问题
- 修复多级表头时固定列隐藏情况计算错误的问题
### 2.0.0 Carbon
#### 非兼容性更新
- Switch
- 由于 `on-*` 属性在 JSX 中会被识别为事件,导致 Switch 所有 `on-*` 属性在 JSX 中无法正常工作,所以 `on-*` 属性更名为 `active-*`,对应地,`off-*` 属性更名为 `inactive-*`。受到影响的属性有:`on-icon-class`、`off-icon-class`、`on-text`、`off-text`、`on-color`、`off-color`、`on-value`、`off-value`
- Table
- `sort-method` 现在和 `Array.sort` 保持一致的逻辑,要求返回一个数字。
### 2.0.0-alpha.3
*2017-10-16*
#### 新特性
- 综合
- 新增全局配置组件尺寸的功能:在引入 Element 时,配置 `size` 字段可以改变所有组件的默认尺寸。当完整引入 Element 时:
```JS
import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element, { size: 'small' })
```
当按需引入 Element 时:
```JS
import Vue from 'vue'
import { Button } from 'element-ui'
Vue.prototype.$ELEMENT = { size: 'small' }
Vue.use(Button)
```
按照以上设置,项目中所有拥有 `size` 属性的组件的默认尺寸均为 'small'。
- Loading
- 配置对象新增 `spinner` 和 `background` 字段,支持自定义加载图标和背景色,#7390
- Autocomplete
- 新增 `debounce` 属性,#7413
- Upload
- 新增 `limit` 和 `on-exceed` 属性,支持对上传文件的个数进行限制,#7405
- Menu
- 新增 `open` 和 `close` 方法,支持手动打开和关闭 SubMenu#7412
- DatePicker
- 新增 `value-format` 属性,支持对绑定值的格式进行自定义,#7367
- TimePicker
- 新增 `arrow-control` 属性,提供另一种交互形式,#7438
- DateTimePicker
- 新增 `time-arrow-control` 属性,用于开启时间选择器的 `arrow-control`#7438
- Form
- Form 和 Form-item 新增 `size` 属性,用于控制表单内组件的尺寸,#7428
- `validate` 方法在不传入 callback 的情况下返回 promise#7405
#### 修复
- 修复部分组件的 `Injection "elFormItem" not found` 报错
#### 非兼容性更新
- DatePicker 的 `change` 事件参数现在为组件的绑定值,格式由 `value-format` 控制
- Input 组件的 `change` 事件现在仅在输入框失去焦点或用户按下回车时触发,与原生 input 元素一致。如果需要实时响应用户的输入,可以使用 `input` 事件
- 最低兼容 Vue 2.5.2 版本
### 2.0.0-alpha.2
*2017-10-05*
- 修正 `theme-chalk` 的主色,#7351
- 修复使用 Dropdown 时控制台报错的问题,#7322
- 修复使用 Menu 时控制台报错的问题,#7321
- ColorPicker 新增 `popper-class` 属性,#7351
- 修复 Button 的 `disabled` 属性无效的问题,#7352
### 2.0.0-alpha.1
*2017-09-30*
*2017-10-27*
#### 新特性
- 综合
- 新增 `theme-chalk` 主题
- 增强以下组件的可访问性Alert、AutoComplete、Breadcrumb、Button、Checkbox、Collapse、Input、InputNumber、Menu、Progress、Radio、Rate、Slider、Switch 和 Upload
- 新增布局组件 Container、Header、Aside、Main 和 Footer
- 新增 TypeScript 类型声明
- 重绘了全部图标,并新增了部分图标
- 新增了一系列基于断点的工具类,用于当视口尺寸满足一定条件时隐藏元素
- 新增全局配置组件尺寸的功能。在引入 Element 时,配置 `size` 字段可以改变所有组件的默认尺寸
- Button
- 新增 `round` 属性,用于圆角按钮 #6643
- TimeSelect
@@ -142,6 +41,7 @@
- TimePicker
- 可以用方向键导航,用 `Enter` 选中时间 #6050
- 新增 `start-placeholder``end-placeholder`,用于设置范围选择时两个输入框的占位符 #7169
- 新增 `arrow-control` 属性,提供另一种交互形式,#7438
- Tree
- 子节点在首次被展开之前不进行渲染 #6257
- 新增 `check-descendants` 属性,设置 `lazy` 模式下勾选节点时,是否完全展开整个子树 #6235
@@ -150,11 +50,14 @@
- Datepicker
- type 为 `datetimerange` 时可以使用 `timeFormat` 格式化时间选择器 #6052
- 新增 `start-placeholder``end-placeholder`,用于设置范围选择时两个输入框的占位符 #7169
- 新增 `value-format` 属性,支持对绑定值的格式进行自定义,#7367
- 新增 `unlink-panels` 属性,用于在选择日期范围时取消两个日期面板之间的联动
- MessageBox
- 新增 `closeOnHashChange` 属性 #6043
- 新增 `center` 属性,提供居中布局 #7029
- 新增 `roundButton` 属性,使得内部按钮为圆角按钮 #7029
- 新增 `dangerouslyUseHTMLString` 属性,使得 `message` 支持传入 HTML 字符串<sup>*</sup> #6043
- 新增 `inputType` 属性,用户指定内部输入框的类型,#7651
- Dialog
- 新增 `width``fullscreen``append-to-body` 属性,支持嵌套使用
- 新增 `center` 属性,提供居中布局 #7042
@@ -163,6 +66,7 @@
- 增加手动输入色值的支持 #6167
- 新增 `size` 属性,用于控制组件的大小 #7026
- 新增 `disabled` 属性,用于禁用组件 #7026
- 新增 `popper-class` 属性,#7351
- Message
- 图标部分使用 icon 代替图片,从而支持通过 CSS 修改图标背景色 #6207
- 新增 `dangerouslyUseHTMLString` 属性,使得 `message` 属性支持传入 HTML 字符串<sup>*</sup> #6207
@@ -183,9 +87,13 @@
- 新增 `center` 属性,提供居中布局 #6876
- Menu
- 新增 `background-color``text-color``active-text-color` 属性,分别用于设置菜单的背景色、菜单的文字颜色和当前激活菜单的文字颜色 #7064
- 新增 `open``close` 方法,支持手动打开和关闭 SubMenu#7412
- Form
- 新增 `inline-message` 属性,设置后校验信息会以行内样式显示 #7032
- 新增 `status-icon` 属性,用于在输入框中显示校验结果反馈图标 #7032
- Form 和 FormItem 新增 `size` 属性,用于控制表单内组件的尺寸,#7428
- `validate` 方法在不传入 callback 的情况下返回 promise#7405
- 新增 `clearValidate` 方法,用于清空所有表单项的验证信息,#7623
- Input
- 新增 `suffix``prefix` 的 slot以及 `suffixIcon``prefixIcon` 属性,用于给输入框内部增加前置和后置内容 #7032
- Breadcrumb
@@ -194,6 +102,33 @@
- 新增 `simple` 属性,用于开启简洁风格的步骤条 #7274
- Pagination
- 新增 `prev-text``next-text` 属性,用于自定义上一页和下一页的文本 #7005
- Loading
- 配置对象新增 `spinner``background` 字段,支持自定义加载图标和背景色,#7390
- Autocomplete
- 新增 `debounce` 属性,#7413
- Upload
- 新增 `limit``on-exceed` 属性,支持对上传文件的个数进行限制,#7405
- DateTimePicker
- 新增 `time-arrow-control` 属性,用于开启时间选择器的 `arrow-control`#7438
- Layout
- 新增断点 `xl`,适用于宽度大于 1920px 的视口
- Table
- 新增 `span-method` 属性,用于合并行或列
- 新增 `clearSort` 方法,用于清空排序状态
- 新增 `clearFilter` 方法,用于清空过滤状态
- 对于可展开行,当该行展开时会获得一个 `.expanded` 类名,方便自定义样式
- 新增 `size` 属性,用于控制表格尺寸
- 新增 `toggleRowExpansion` 方法,用于手动展开或关闭行
- 新增 `cell-class-name` 属性,用于指定单元格的类名
- 新增 `cell-style` 属性,用于指定单元格的样式
- 新增 `header-row-class-name` 属性,用于指定表头行的类名
- 新增 `header-row-style` 属性,用于指定表头行的样式
- 新增 `header-cell-class-name` 属性,用于指定表头单元格的类名
- 新增 `header-cell-style` 属性,用于指定表头单元格的样式
- TableColumn 的 `prop` 属性支持 `object[key]` 格式
- TableColumn 新增 `index` 属性,用于自定义索引值
- Select
- 新增 `reserve-keyword` 属性,用于在选择某个选项后保留当前的搜索关键词
#### 修复
- DatePicker
@@ -208,12 +143,22 @@
- 当含有下拉框时,下拉框的打开和关闭会造成文字虚晃的问题 #6088
- Select
- 提升性能,修复组件销毁时可能导致 Vue dev-tool 卡死的问题 #6151
- Table
- 修复 Table 在父元素从 `display: none` 变成其他状态时会隐藏的问题
- 修复 Table 在父元素为 `display: flex` 时可能出现的宽度逐渐变大的问题
- 修复 `append` 具名 slot 和固定列并存时,动态获取表格数据会导致固定列消失的问题
- 修复 `expand-row-keys` 属性初始化无效的问题
- 修复 `data` 改变时过滤条件失效的问题
- 修复多级表头时固定列隐藏情况计算错误的问题
- 修复 `max-height` 变更后无法恢复的问题
- 修复一些样式上的计算错误
#### 非兼容性更新
- 综合
- 移除 `theme-default`
- 最低兼容 Vue 2.5.2 和 IE 10
- 表单组件的 `change` 事件和 Pagination 的 `current-change` 事件现在仅响应用户交互
- Button 和表单组件的 `size` 属性不再接受 `large` 值,可接受 `medium`、`small` 和 `mini`
- Button 和表单组件的 `size` 属性现在可接受 `medium``small``mini`
- 为了方便使用第三方图标Button 的 `icon` 属性、Input 的 `prefix-icon``suffix-icon` 属性、Steps 的 `icon` 属性现在需要传入完整的图标类名
- Dialog
- 移除 `size` 属性。现在 Dialog 的尺寸由 `width``fullscreen` 控制
@@ -225,23 +170,30 @@
- Transfer
- `footer-format` 属性更名为 `format`
- Switch
- `on-text` 和 `off-text` 属性不再有默认值
- 由于 `on-*` 属性在 JSX 中会被识别为事件,导致 Switch 所有 `on-*` 属性在 JSX 中无法正常工作,所以 `on-*` 属性更名为 `active-*`,对应地,`off-*` 属性更名为 `inactive-*`。受到影响的属性有:`on-icon-class``off-icon-class``on-text``off-text``on-color``off-color``on-value``off-value`
- `active-text``inactive-text` 属性不再有默认值
- Tag
- `type` 属性现在支持 `success``info``warning``danger` 四个值
- `close-transition` 属性更名为 `disable-transitions`
- Menu
- 移除 `theme` 属性。现在通过 `background-color``text-color``active-text-color` 属性进行颜色的自定义
- Input
- 移除 `icon` 属性。现在通过 `suffix-icon` 属性或者 `suffix` 具名 slot 来加入尾部图标
- 移除 `on-icon-click` 属性和 `click` 事件。现在如果需要为输入框中的图标添加点击事件,请以具名 slot 的方式添加图标
- `change` 事件现在仅在输入框失去焦点或用户按下回车时触发,与原生 input 元素一致。如果需要实时响应用户的输入,可以使用 `input` 事件
- Autocomplete
- 移除 `icon` 和 `on-icon-click` 属性。现在通过 `prefix` 和 `suffix` 具名 slot 来加入图标
- 移除 `custom-item` 属性。现在通过 `scoped slot` 自定义输入建议列表项的内容
- Table
- 移除通过 `inline-template` 自定义列模板的功能
- 移除 `props` 属性,现在使用 `value-key` 属性指定输入建议对象中用于显示的键名
- Steps
- 移除 `center` 属性
- 现在步骤条将默认充满父容器
- DatePicker
- `change` 事件参数现在为组件的绑定值,格式由 `value-format` 控制
- Table
- 移除通过 `inline-template` 自定义列模板的功能
- `sort-method` 现在和 `Array.sort` 保持一致的逻辑,要求返回一个数字
-`append` slot 移至 `tbody` 元素以外,以保证其只被渲染一次
- `expand` 事件更名为 `expand-change`,以保证 API 的命名一致性
- `row-class-name``row-style` 的函数参数改为对象,以保证 API 的一致性
##
<i><sup>*</sup> 在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 [XSS 攻击](https://en.wikipedia.org/wiki/Cross-site_scripting)。因此请在 `dangerouslyUseHTMLString` 打开的情况下,确保 `message` 的内容是可信的,**永远不要**将用户提交的内容赋值给 `message` 属性。</i>

View File

@@ -67,7 +67,7 @@ Vue.component(Button.name, Button)
For more information, please refer to [Quick Start](http://element.eleme.io/#/en-US/component/quickstart) in our documentation.
## Browser Support
Modern browsers and Internet Explorer 9+.
Modern browsers and Internet Explorer 10+.
## Development
Skip this part if you just want to use Element.

View File

@@ -42,11 +42,10 @@ if [ "$TRAVIS_TAG" ]; then
SUB_FOLDER='2.0'
mkdir $SUB_FOLDER
# rm -rf *.js *.css *.map static
rm -rf *.js *.css *.map static
rm -rf $SUB_FOLDER/**
# cp -rf ../../examples/element-ui/** .
cp -rf ../../examples/element-ui/** .
cp -rf ../../examples/element-ui/** $SUB_FOLDER/
cp -rf ../../examples/element-ui/versions.json .
git add -A .
git commit -m "$TRAVIS_COMMIT_MSG"
git push origin gh-pages

View File

@@ -7,12 +7,12 @@ git clone -b gh-pages https://github.com/ElemeFE/element.git && cd element
# build sub folder
SUB_FOLDER='2.0'
mkdir $SUB_FOLDER
# rm -rf *.js *.css *.map static
rm -rf *.js *.css *.map static
rm -rf $SUB_FOLDER/**
# cp -rf ../../examples/element-ui/** .
cp -rf ../../examples/element-ui/** .
cp -rf ../../examples/element-ui/** $SUB_FOLDER/
cp -rf ../../examples/element-ui/versions.json .
cd ../..
# deploy domestic site
faas deploy alpha
faas deploy alpha
rm -rf temp_web

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env sh
git checkout carbon
git checkout dev
if test -n "$(git status --porcelain)"; then
echo 'Unclean working tree. Commit or stash changes first.' >&2;

View File

@@ -1,3 +1,6 @@
git checkout master
git merge dev
#!/usr/bin/env sh
set -e
echo "Enter release version: "
@@ -16,7 +19,12 @@ then
echo "Releasing theme-chalk $VERSION ..."
cd packages/theme-chalk
npm version $VERSION --message "[release] $VERSION"
npm publish
if [[ $VERSION =~ "beta" ]]
then
npm publish --tag beta
else
npm publish
fi
cd ../..
# commit
@@ -25,8 +33,16 @@ then
npm version $VERSION --message "[release] $VERSION"
# publish
git push eleme carbon
git push eleme master
git push eleme refs/tags/v$VERSION
git checkout dev
git rebase master
git push eleme dev
npm publish --tag next
if [[ $VERSION =~ "beta" ]]
then
npm publish --tag beta
else
npm publish
fi
fi

View File

@@ -202,7 +202,10 @@
},
watch: {
lang() {
lang(val) {
if (val === 'zh-CN') {
this.suggestJump();
}
this.localize();
}
},
@@ -210,11 +213,57 @@
methods: {
localize() {
use(this.lang === 'zh-CN' ? zhLocale : enLocale);
},
suggestJump() {
const href = location.href;
const preferGithub = localStorage.getItem('PREFER_GITHUB');
if (href.indexOf('element-cn') > -1 || preferGithub) return;
setTimeout(() => {
this.$confirm('建议大陆用户访问部署在国内的站点,是否跳转?', '提示')
.then(() => {
location.href = location.href.replace('element.', 'element-cn.');
})
.catch(() => {
localStorage.setItem('PREFER_GITHUB', true);
});
}, 1000);
}
},
mounted() {
this.localize();
if (this.lang === 'zh-CN') {
this.suggestJump();
}
setTimeout(() => {
const notified = localStorage.getItem('RELEASE_NOTIFIED');
if (!notified) {
const h = this.$createElement;
const title = this.lang === 'zh-CN'
? '2.0 正式发布'
: '2.0 available now';
const messages = this.lang === 'zh-CN'
? ['点击', '这里', '查看详情']
: ['Click ', 'here', ' to learn more'];
this.$notify({
title,
duration: 0,
message: h('span', [
messages[0],
h('a', {
attrs: {
target: '_blank',
href: `https://github.com/ElemeFE/element/issues/${ this.lang === 'zh-CN' ? '7755' : '7756' }`
}
}, messages[1]),
messages[2]
]),
onClose() {
localStorage.setItem('RELEASE_NOTIFIED', 1);
}
});
}
}, 3500);
}
};
</script>

View File

@@ -178,6 +178,7 @@
<script type="text/babel">
import compoLang from '../i18n/component.json';
import { version } from 'main/index.js';
export default {
data() {
@@ -200,10 +201,10 @@
goJsfiddle() {
const { script, html, style } = this.jsfiddle;
const resourcesTpl = '<scr' + 'ipt src="//unpkg.com/vue/dist/vue.js"></scr' + 'ipt>' +
'\n<scr' + 'ipt src="//unpkg.com/element-ui@next/lib/index.js"></scr' + 'ipt>';
'\n<scr' + `ipt src="//unpkg.com/element-ui@${ version }/lib/index.js"></scr` + 'ipt>';
let jsTpl = (script || '').replace(/export default/, 'var Main =').trim();
let htmlTpl = `${resourcesTpl}\n<div id="app">\n${html.trim()}\n</div>`;
let cssTpl = `@import url("//unpkg.com/element-ui@next/lib/theme-chalk/index.css");\n${(style || '').trim()}\n`;
let cssTpl = `@import url("//unpkg.com/element-ui@${ version }/lib/theme-chalk/index.css");\n${(style || '').trim()}\n`;
jsTpl = jsTpl
? jsTpl + '\nvar Ctor = Vue.extend(Main)\nnew Ctor().$mount(\'#app\')'
: 'new Vue().$mount(\'#app\')';

View File

@@ -390,7 +390,11 @@
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = _ => {
if (xhr.readyState === 4 && xhr.status === 200) {
this.versions = JSON.parse(xhr.responseText);
const versions = JSON.parse(xhr.responseText);
this.versions = Object.keys(versions).slice(-2).reduce((prev, next) => {
prev[next] = versions[next];
return prev;
}, {});
}
};
xhr.open('GET', '/versions.json');

View File

@@ -128,10 +128,27 @@
}
};
const shadeColor = (color, shade) => {
let red = parseInt(color.slice(0, 2), 16);
let green = parseInt(color.slice(2, 4), 16);
let blue = parseInt(color.slice(4, 6), 16);
red = Math.round((1 - shade) * red);
green = Math.round((1 - shade) * green);
blue = Math.round((1 - shade) * blue);
red = red.toString(16);
green = green.toString(16);
blue = blue.toString(16);
return `#${ red }${ green }${ blue }`;
};
const clusters = [theme];
for (let i = 0; i <= 9; i++) {
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
}
clusters.push(shadeColor(theme, 0.1));
return clusters;
}
}

View File

@@ -5,15 +5,17 @@
if (!value) {
return callback(new Error('Please input the age'));
}
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'));
} else {
if (value < 18) {
callback(new Error('Age must be greater than 18'));
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'));
} else {
callback();
if (value < 18) {
callback(new Error('Age must be greater than 18'));
} else {
callback();
}
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
@@ -338,7 +340,8 @@ When the vertical space is limited and the form is relatively simple, you can pu
<el-option label="Zone one" value="shanghai"></el-option>
<el-option label="Zone two" value="beijing"></el-option>
</el-select>
</el-form-item><el-form-item>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Query</el-button>
</el-form-item>
</el-form>
@@ -546,15 +549,17 @@ This example shows how to customize your own validation rules to finish a two-fa
if (!value) {
return callback(new Error('Please input the age'));
}
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'));
} else {
if (value < 18) {
callback(new Error('Age must be greater than 18'));
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'));
} else {
callback();
if (value < 18) {
callback(new Error('Age must be greater than 18'));
} else {
callback();
}
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {

View File

@@ -4,21 +4,21 @@
Installing with npm is recommended and it works seamlessly with [webpack](https://webpack.js.org/).
```shell
npm i element-ui@next -S
npm i element-ui -S
```
### CDN
Get the latest version from [unpkg.com/element-ui](https://unpkg.com/element-ui@next/) , and import JavaScript and CSS file in your page.
Get the latest version from [unpkg.com/element-ui](https://unpkg.com/element-ui/) , and import JavaScript and CSS file in your page.
```html
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui@next/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui@next/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
```
### Hello world
If you are using CDN, a hello-world page is easy with Element. [Online Demo](https://jsfiddle.net/leopoldthecuber/hzfpyvg6/1/)
If you are using CDN, a hello-world page is easy with Element. [Online Demo](https://jsfiddle.net/hzfpyvg6/14/)
```html
<!DOCTYPE html>
@@ -26,7 +26,7 @@ If you are using CDN, a hello-world page is easy with Element. [Online Demo](htt
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui@next/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
@@ -39,7 +39,7 @@ If you are using CDN, a hello-world page is easy with Element. [Online Demo](htt
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui@next/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',

View File

@@ -4,125 +4,19 @@ This part walks you through the process of using Element in a webpack project.
### Use Starter Kit
Under construction.
We provide a general [project template](https://github.com/ElementUI/element-starter) for you. For Laravel users, we also have a [template](https://github.com/ElementUI/element-in-laravel-starter). You can download and use them directly.
### Config files
If you prefer not to use them, please read the following.
Create a new project, and its structure should be
```text
|- src/ --------------------- source code
|- App.vue
|- main.js -------------- entry
|- .babelrc ----------------- babel config
|- index.html --------------- HTML template
|- package.json ------------- npm config
|- README.md ---------------- readme
|- webpack.config.js -------- webpack config
```
### Use vue-cli
Typical configurations for these config files are:
We can also start a project using [vue-cli](https://github.com/vuejs/vue-cli):
**.babelrc**
```json
{
"presets": ["vue-app"]
}
```
<br>
**package.json**
```json
{
"name": "element-starter",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --port 8086",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"element-ui": "next",
"vue": "^2.4.2"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-preset-vue-app": "^1.2.0",
"cross-env": "^1.0.6",
"css-loader": "^0.23.1",
"file-loader": "^0.8.5",
"style-loader": "^0.13.1",
"vue-loader": "^9.8.0",
"webpack": "beta",
"webpack-dev-server": "beta"
}
}
```
<br>
**webpack.config.js**
```javascript
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
loader: 'file-loader'
},
{
test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
loader: 'file-loader',
query: {
name: '[name].[ext]?[hash]'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
])
}
```shell
> npm i -g vue-cli
> mkdir my-project && cd my-project
> vue init webpack
> npm i && npm i element-ui
```
### Import Element

View File

@@ -1263,7 +1263,7 @@ 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`. Set table attribute `default-sort` to determine default sort column and order. To apply your own sorting rules, use `sort-method`. If you need remote sorting from backend, set `sortable` to `custom`, and listen to the `sort-change` event on Table. In the event handler, you have access to the sorting column and sorting order so that you can fetch sorted table data from API. 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 attribute `sortable` in a certain column to sort the data based on this column. It accepts `Boolean` with a default value `false`. Set table attribute `default-sort` to determine default sort column and order. To apply your own sorting rules, use `sort-method` or `sort-by`. If you need remote sorting from backend, set `sortable` to `custom`, and listen to the `sort-change` event on Table. In the event handler, you have access to the sorting column and sorting order so that you can fetch sorted table data from API. 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
@@ -2010,6 +2010,7 @@ You can customize row index in `type=index` columns.
| render-header | render function for table header of this column | Function(h, { column, $index }) | — | — |
| sortable | whether column can be sorted. Remote sorting can be done by setting this attribute to 'custom' and listening to the `sort-change` event of Table | boolean, string | true, false, custom | false |
| sort-method | sorting method, works when `sortable` is `true`. Should return a number, just like Array.sort | Function(a, b) | — | — |
| sort-by | specify which property to sort by, works when `sortable` is `true` and `sort-method` is `undefined`. If set to an Array, the column will sequentially sort by the next property if the previous one is equal | Function(row, index)/String/Array | — | — |
| resizable | whether column width can be resized, works when `border` of `el-table` is `true` | boolean | — | false |
| formatter | function that formats cell content | Function(row, column, cellValue) | — | — |
| show-overflow-tooltip | whether to hide extra content and show them in a tooltip when hovering on the cell | boolean | — | false |

View File

@@ -5,15 +5,17 @@
if (!value) {
return callback(new Error('年龄不能为空'));
}
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
callback();
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
@@ -331,7 +333,8 @@
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item><el-form-item>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
@@ -537,15 +540,17 @@
if (!value) {
return callback(new Error('年龄不能为空'));
}
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
callback();
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {

View File

@@ -4,21 +4,21 @@
推荐使用 npm 的方式安装,它能更好地和 [webpack](https://webpack.js.org/) 打包工具配合使用。
```shell
npm i element-ui@next -S
npm i element-ui -S
```
### CDN
目前可以通过 [unpkg.com/element-ui](https://unpkg.com/element-ui@next/) 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。
目前可以通过 [unpkg.com/element-ui](https://unpkg.com/element-ui/) 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。
```html
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui@next/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui@next/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
```
### Hello world
通过 CDN 的方式我们可以很容易地使用 Element 写出一个 Hello world 页面。[在线演示](https://jsfiddle.net/leopoldthecuber/hzfpyvg6/1/)
通过 CDN 的方式我们可以很容易地使用 Element 写出一个 Hello world 页面。[在线演示](https://jsfiddle.net/hzfpyvg6/14/)
```html
<!DOCTYPE html>
@@ -26,7 +26,7 @@ npm i element-ui@next -S
<head>
<meta charset="UTF-8">
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui@next/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
@@ -39,7 +39,7 @@ npm i element-ui@next -S
<!-- 先引入 Vue -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui@next/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',

View File

@@ -4,125 +4,19 @@
### 使用 Starter Kit
整理中
我们提供了通用的[项目模板](https://github.com/ElementUI/element-starter),你可以直接使用。对于 Laravel 用户,我们也准备了相应的[模板](https://github.com/ElementUI/element-in-laravel-starter),同样可以直接下载使用
### 配置文件
如果不希望使用我们提供的模板,请继续阅读。
新建项目,项目结构为
```text
|- src/ --------------------- 项目源代码
|- App.vue
|- main.js -------------- 入口文件
|- .babelrc ----------------- babel 配置文件
|- index.html --------------- HTML 模板
|- package.json ------------- npm 配置文件
|- README.md ---------------- 项目帮助文档
|- webpack.config.js -------- webpack 配置文件
```
### 使用 vue-cli
几个配置文件的典型配置如下:
我们还可以使用 [vue-cli](https://github.com/vuejs/vue-cli) 初始化项目,命令如下:
**.babelrc**
```json
{
"presets": ["vue-app"]
}
```
<br>
**package.json**
```json
{
"name": "element-starter",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --port 8086",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"element-ui": "next",
"vue": "^2.4.2"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-preset-vue-app": "^1.2.0",
"cross-env": "^1.0.6",
"css-loader": "^0.23.1",
"file-loader": "^0.8.5",
"style-loader": "^0.13.1",
"vue-loader": "^9.8.0",
"webpack": "beta",
"webpack-dev-server": "beta"
}
}
```
<br>
**webpack.config.js**
```javascript
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
loader: 'file-loader'
},
{
test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
loader: 'file-loader',
query: {
name: '[name].[ext]?[hash]'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
])
}
```shell
> npm i -g vue-cli
> mkdir my-project && cd my-project
> vue init webpack
> npm i && npm i element-ui
```
### 引入 Element

View File

@@ -298,10 +298,10 @@
return row.tag === value;
},
tableRowClassName({row, rowndex}) {
if (rowndex === 1) {
tableRowClassName({row, rowIndex}) {
if (rowIndex === 1) {
return 'warning-row';
} else if (rowndex === 3) {
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
@@ -1303,7 +1303,7 @@
对表格进行排序,可快速查找或对比数据。
:::demo 在列中设置`sortable`属性即可实现以该列为基准的排序,接受一个`Boolean`,默认为`false`。可以通过 Table 的`default-sort`属性设置默认的排序列和排序顺序。可以使用`sort-method`使用自定义的排序规则。如果需要后端排序,需将`sortable`设置为`custom`,同时在 Table 上监听`sort-change`事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。在本例中,我们还使用了`formatter`属性,它用于格式化指定列的值,接受一个`Function`,会传入两个参数:`row``column`,可以根据自己的需求进行处理。
:::demo 在列中设置`sortable`属性即可实现以该列为基准的排序,接受一个`Boolean`,默认为`false`。可以通过 Table 的`default-sort`属性设置默认的排序列和排序顺序。可以使用`sort-method`或者`sort-by`使用自定义的排序规则。如果需要后端排序,需将`sortable`设置为`custom`,同时在 Table 上监听`sort-change`事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。在本例中,我们还使用了`formatter`属性,它用于格式化指定列的值,接受一个`Function`,会传入两个参数:`row``column`,可以根据自己的需求进行处理。
```html
<template>
<el-table
@@ -2073,6 +2073,7 @@
| render-header | 列标题 Label 区域渲染使用的 Function | Function(h, { column, $index }) | — | — |
| sortable | 对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件 | boolean, string | true, false, 'custom' | false |
| sort-method | 对数据进行排序的时候使用的方法,仅当 sortable 设置为 true 的时候有效,需返回一个数字,和 Array.sort 表现一致 | Function(a, b) | — | — |
| sort-by | 指定数据按照哪个属性进行排序,仅当 sortable 设置为 true 且没有设置 sort-method 的时候有效。如果 sort-by 为数组,则先按照第 1 个属性排序,如果第 1 个相等,再按照第 2 个排序,以此类推。 | String/Array/Function(row, index) | — | — |
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | Function(row, column, cellValue) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | Boolean | — | false |

View File

@@ -5,7 +5,7 @@
"index": {
"lang": "zh-CN",
"titleSize": "34",
"paraSize": "20",
"paraSize": "18",
"1": "网站快速成型工具",
"2": "Element一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库",
"3": "指南",
@@ -97,7 +97,7 @@
"index": {
"lang": "en-US",
"titleSize": "34",
"paraSize": "20",
"paraSize": "18",
"theatreParam": "{ maxSpeed: 100 }",
"typingFunc": ".addScene('product designers', 1800, -17, 800)\n .addScene('UI designers', 1800, -12, 800)\n .addScene('UX designers', 1800, -12, 800)\n .addScene('product managers', 1800, -16, 800)\n .addScene('FE developers', 1800, -13, 800)",
"typingInvoke": ".addActor('line2', { speed: 1, accuracy: 1 })\n .addScene(2600)\n .addScene('line2:For ', 500)",

View File

@@ -16,7 +16,7 @@
font-size: <%= paraSize >px;
line-height: 28px;
color: #888;
margin: 15px 0 0;
margin: 10px 0 5px;
}
}
.jumbotron {
@@ -245,6 +245,9 @@
<div>
<img class="jumbotron-plant-2" src="~examples/assets/images/plant-2.png" alt="">
<img class="jumbotron-web" src="~examples/assets/images/web.png" alt="">
<img class="jumbotron-plant-1" src="~examples/assets/images/plant-1.png" alt="">
<img class="jumbotron-figure-1" src="~examples/assets/images/figure-1.png" alt="">
<img class="jumbotron-figure-2" src="~examples/assets/images/figure-2.png" alt="">
</div>
<div data-hover-layer="0">
<img class="jumbotron-cloud-1" src="~examples/assets/images/cloud-1.png" alt="">
@@ -255,11 +258,6 @@
<img class="jumbotron-compo-2" src="~examples/assets/images/compo-2.png" alt="">
<img class="jumbotron-compo-3" src="~examples/assets/images/compo-3.png" alt="">
</div>
<div data-hover-layer="2">
<img class="jumbotron-plant-1" src="~examples/assets/images/plant-1.png" alt="">
<img class="jumbotron-figure-1" src="~examples/assets/images/figure-1.png" alt="">
<img class="jumbotron-figure-2" src="~examples/assets/images/figure-2.png" alt="">
</div>
</div>
<div class="cards">
<ul class="container">
@@ -309,17 +307,14 @@
export default {
mounted() {
new Hover('.jumbotron', { // eslint-disable-line
max: 1,
max: 3,
scale: 1,
perspective: 700,
layers: [{
multiple: 0.01,
reverseTranslate: true
}, {
multiple: 0.04,
reverseTranslate: true
}, {
multiple: 0.015,
multiple: 0.02,
reverseTranslate: true
}]
});

View File

@@ -1 +1 @@
{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.8":"1.4","2.0.0-rc.1":"2.0"}
{"1.0.9":"1.0","1.1.6":"1.1","1.2.9":"1.2","1.3.7":"1.3","1.4.8":"1.4","2.0.2":"2.0"}

View File

@@ -1,6 +1,6 @@
{
"name": "element-ui",
"version": "2.0.0-rc.1",
"version": "2.0.2",
"description": "A Component Library for Vue.js.",
"main": "lib/element-ui.common.js",
"files": [
@@ -57,7 +57,7 @@
"throttle-debounce": "^1.0.1"
},
"peerDependencies": {
"vue": "^2.3.0"
"vue": "^2.5.2"
},
"devDependencies": {
"algoliasearch": "^3.24.5",

View File

@@ -165,9 +165,15 @@
}
},
handleChange(ev) {
if (this.isLimitExceeded) return;
let value;
if (ev.target.checked) {
value = this.trueLabel === undefined ? true : this.trueLabel;
} else {
value = this.falseLabel === undefined ? false : this.falseLabel;
}
this.$emit('change', value, ev);
this.$nextTick(() => {
if (this.isLimitExceeded) return;
this.$emit('change', this.model, ev);
if (this._checkboxGroup) {
this.dispatch('ElCheckboxGroup', 'change', [this._checkboxGroup.value]);
}

View File

@@ -42,7 +42,7 @@
</script>
<template>
<div class="el-checkbox-group" role="group" aria-label="checkbox-group">
<div class="el-checkbox-group" role="group" aria-label="checkbox-group">
<slot></slot>
</div>
</template>

View File

@@ -176,9 +176,15 @@
}
},
handleChange(ev) {
if (this.isLimitExceeded) return;
let value;
if (ev.target.checked) {
value = this.trueLabel === undefined ? true : this.trueLabel;
} else {
value = this.falseLabel === undefined ? false : this.falseLabel;
}
this.$emit('change', value, ev);
this.$nextTick(() => {
if (this.isLimitExceeded) return;
this.$emit('change', this.model, ev);
if (this.isGroup) {
this.dispatch('ElCheckboxGroup', 'change', [this._checkboxGroup.value]);
}

View File

@@ -14,7 +14,7 @@
tabindex="0"
@keyup.space.enter.stop="handleEnterClick"
:class="{'focusing': focusing}"
@focus="focusing = true"
@focus="handleFocus"
@blur="focusing = false"
>
<i class="el-collapse-item__arrow el-icon-arrow-right"></i>
@@ -58,7 +58,8 @@
display: 'block'
},
contentHeight: 0,
focusing: false
focusing: false,
isClick: false
};
},
@@ -84,9 +85,19 @@
},
methods: {
handleFocus() {
setTimeout(() => {
if (!this.isClick) {
this.focusing = true;
} else {
this.isClick = false;
}
}, 50);
},
handleHeaderClick() {
this.dispatch('ElCollapse', 'item-click', this);
this.focusing = false;
this.isClick = true;
},
handleEnterClick() {
this.dispatch('ElCollapse', 'item-click', this);

View File

@@ -3,6 +3,7 @@
<template v-if="!arrowControl">
<el-scrollbar
@mouseenter.native="emitSelectRange('hours')"
@mousemove.native="adjustCurrentSpinner('hours')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
@@ -18,6 +19,7 @@
</el-scrollbar>
<el-scrollbar
@mouseenter.native="emitSelectRange('minutes')"
@mousemove.native="adjustCurrentSpinner('minutes')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
@@ -33,6 +35,7 @@
<el-scrollbar
v-show="showSeconds"
@mouseenter.native="emitSelectRange('seconds')"
@mousemove.native="adjustCurrentSpinner('seconds')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
@@ -196,16 +199,10 @@
emitSelectRange(type) {
if (type === 'hours') {
this.$emit('select-range', 0, 2);
this.adjustSpinner('minutes', this.minutes);
this.adjustSpinner('seconds', this.seconds);
} else if (type === 'minutes') {
this.$emit('select-range', 3, 5);
this.adjustSpinner('hours', this.hours);
this.adjustSpinner('seconds', this.seconds);
} else if (type === 'seconds') {
this.$emit('select-range', 6, 8);
this.adjustSpinner('minutes', this.minutes);
this.adjustSpinner('hours', this.hours);
}
this.currentScrollbar = type;
},
@@ -237,6 +234,10 @@
this.adjustSpinner('seconds', this.seconds);
},
adjustCurrentSpinner(type) {
this.adjustSpinner(type, this[type]);
},
adjustSpinner(type, value) {
if (this.arrowControl) return;
const el = this.$refs[type].wrap;

View File

@@ -89,19 +89,19 @@
@click="leftPrevMonth"
class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
<button
type="button"
@click="leftNextYear"
v-if="unlinkPanels"
:disabled="!enableYearArrow"
:class="{ 'is-disabled': !enableYearArrow }"
class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
type="button"
@click="leftNextYear"
v-if="unlinkPanels"
:disabled="!enableYearArrow"
:class="{ 'is-disabled': !enableYearArrow }"
class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
<button
type="button"
@click="leftNextMonth"
v-if="unlinkPanels"
:disabled="!enableMonthArrow"
:class="{ 'is-disabled': !enableMonthArrow }"
class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
type="button"
@click="leftNextMonth"
v-if="unlinkPanels"
:disabled="!enableMonthArrow"
:class="{ 'is-disabled': !enableMonthArrow }"
class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
<div>{{ leftLabel }}</div>
</div>
<date-table
@@ -120,19 +120,19 @@
<div class="el-picker-panel__content el-date-range-picker__content is-right">
<div class="el-date-range-picker__header">
<button
type="button"
@click="rightPrevYear"
v-if="unlinkPanels"
:disabled="!enableYearArrow"
:class="{ 'is-disabled': !enableYearArrow }"
class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
type="button"
@click="rightPrevYear"
v-if="unlinkPanels"
:disabled="!enableYearArrow"
:class="{ 'is-disabled': !enableYearArrow }"
class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
<button
type="button"
@click="rightPrevMonth"
v-if="unlinkPanels"
:disabled="!enableMonthArrow"
:class="{ 'is-disabled': !enableMonthArrow }"
class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
type="button"
@click="rightPrevMonth"
v-if="unlinkPanels"
:disabled="!enableMonthArrow"
:class="{ 'is-disabled': !enableMonthArrow }"
class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
<button
type="button"
@click="rightNextYear"
@@ -336,7 +336,6 @@
if (val && this.$refs.minTimePicker) {
this.$refs.minTimePicker.date = val;
this.$refs.minTimePicker.value = val;
this.$refs.minTimePicker.adjustSpinners();
}
},
@@ -344,7 +343,6 @@
if (val && this.$refs.maxTimePicker) {
this.$refs.maxTimePicker.date = val;
this.$refs.maxTimePicker.value = val;
this.$refs.maxTimePicker.adjustSpinners();
}
},
@@ -406,7 +404,7 @@
this.maxDate = null;
this.leftDate = calcDefaultValue(this.defaultValue)[0];
this.rightDate = nextMonth(this.leftDate);
this.handleConfirm(false);
this.$emit('pick', null);
},
handleChangeRange(val) {
@@ -484,6 +482,12 @@
this.onPick && this.onPick(val);
this.maxDate = val.maxDate;
this.minDate = val.minDate;
// workaround for https://github.com/ElemeFE/element/issues/7539, should remove this block when we don't have to care about Chromium 55 - 57
setTimeout(() => {
this.maxDate = val.maxDate;
this.minDate = val.minDate;
}, 10);
if (!close || this.showTime) return;
this.handleConfirm();
},

View File

@@ -214,7 +214,7 @@
handleClear() {
this.date = this.defaultValue ? new Date(this.defaultValue) : new Date();
this.$emit('pick');
this.$emit('pick', null);
},
emit(value, ...args) {

View File

@@ -135,9 +135,6 @@
this.maxDate = advanceTime(new Date(), 60 * 60 * 1000);
}
}
if (this.visible) {
this.$nextTick(_ => this.adjustSpinners());
}
},
visible(val) {
@@ -150,7 +147,7 @@
methods: {
handleClear() {
this.$emit('pick', []);
this.$emit('pick', null);
},
handleCancel() {

View File

@@ -90,7 +90,7 @@
},
handleClear() {
this.$emit('pick');
this.$emit('pick', null);
},
scrollToOption(selector = '.selected') {

View File

@@ -51,6 +51,8 @@
if (val) {
this.oldValue = this.value;
this.$nextTick(() => this.$refs.spinner.emitSelectRange('hours'));
} else {
this.needInitAdjust = true;
}
},
@@ -63,8 +65,9 @@
}
this.date = date;
if (this.visible) {
if (this.visible && this.needInitAdjust) {
this.$nextTick(_ => this.adjustSpinners());
this.needInitAdjust = false;
}
},
@@ -90,7 +93,8 @@
selectableRange: [],
selectionRange: [0, 2],
disabled: false,
arrowControl: false
arrowControl: false,
needInitAdjust: true
};
},

View File

@@ -5,6 +5,7 @@
:readonly="!editable || readonly"
:disabled="disabled"
:size="pickerSize"
:id="id"
:name="name"
v-if="!ranged"
v-clickoutside="handleClose"
@@ -47,6 +48,8 @@
:placeholder="startPlaceholder"
:value="displayValue && displayValue[0]"
:disabled="disabled"
:id="id && id[0]"
:name="name && name[0]"
@input="handleStartInput"
@change="handleStartChange"
@focus="handleFocus"
@@ -56,6 +59,8 @@
:placeholder="endPlaceholder"
:value="displayValue && displayValue[1]"
:disabled="disabled"
:id="id && id[1]"
:name="name && name[1]"
@input="handleEndInput"
@change="handleEndChange"
@focus="handleFocus"
@@ -157,8 +162,14 @@ const TYPE_VALUE_RESOLVER_MAP = {
},
week: {
formatter(value, format) {
let date = formatDate(value, format);
const week = getWeekNumber(value);
let week = getWeekNumber(value);
let month = value.getMonth();
const trueDate = new Date(value);
if (week === 1 && month === 11) {
trueDate.setHours(0, 0, 0, 0);
trueDate.setDate(trueDate.getDate() + 3 - (trueDate.getDay() + 6) % 7);
}
let date = formatDate(trueDate, format);
date = /WW/.test(date)
? date.replace(/WW/, week < 10 ? '0' + week : week)
@@ -266,6 +277,20 @@ const valueEquals = function(a, b) {
return false;
};
const isString = function(val) {
return typeof val === 'string' || val instanceof String;
};
const validator = function(val) {
// either: String, Array of String, null / undefined
return (
val === null ||
val === undefined ||
isString(val) ||
(Array.isArray(val) && val.length === 2 && val.every(isString))
);
};
export default {
mixins: [Emitter, NewPopper, Focus('reference')],
@@ -283,12 +308,19 @@ export default {
placeholder: String,
startPlaceholder: String,
endPlaceholder: String,
name: String,
name: {
default: '',
validator
},
disabled: Boolean,
clearable: {
type: Boolean,
default: true
},
id: {
default: '',
validator
},
popperClass: String,
editable: {
type: Boolean,

View File

@@ -53,7 +53,10 @@
label: String,
labelWidth: String,
prop: String,
required: Boolean,
required: {
type: Boolean,
default: undefined
},
rules: [Object, Array],
error: String,
validateStatus: String,
@@ -163,8 +166,9 @@
},
methods: {
validate(trigger, callback = noop) {
this.validateDisabled = false;
var rules = this.getFilteredRule(trigger);
if ((!rules || rules.length === 0) && !this._props.hasOwnProperty('required')) {
if ((!rules || rules.length === 0) && this.required === undefined) {
callback();
return true;
}
@@ -215,7 +219,7 @@
getRules() {
var formRules = this.form.rules;
var selfRules = this.rules;
var requiredRule = this._props.hasOwnProperty('required') ? { required: !!this.required } : [];
var requiredRule = this.required !== undefined ? { required: !!this.required } : [];
formRules = formRules ? formRules[this.prop] : [];
@@ -254,7 +258,7 @@
let rules = this.getRules();
if (rules.length || this._props.hasOwnProperty('required')) {
if (rules.length || this.required !== undefined) {
this.$on('el.form.blur', this.onFieldBlur);
this.$on('el.form.change', this.onFieldChange);
}

View File

@@ -80,7 +80,19 @@
console.warn('[Element Warn][Form]model is required for validate to work!');
return;
}
let promise;
// if no callback, return promise
if (typeof callback !== 'function' && window.Promise) {
promise = new window.Promise((resolve, reject) => {
callback = function(valid) {
valid ? resolve(valid) : reject(valid);
};
});
}
let valid = true;
let count = 0;
// 如果需要验证的fields为空调用验证时立刻返回callback
if (this.fields.length === 0 && callback) {
callback(true);
@@ -90,13 +102,14 @@
if (errors) {
valid = false;
}
if (typeof callback === 'function' && ++count === this.fields.length) {
callback(valid);
}
});
});
if (typeof callback === 'function') {
callback(valid);
} else if (window.Promise) {
return Promise[valid ? 'resolve' : 'reject'](valid); // eslint-disable-line
if (promise) {
return promise;
}
},
validateField(prop, cb) {

View File

@@ -208,6 +208,15 @@
if (value === '') {
return;
}
if (value.indexOf('.') === (value.length - 1)) {
return;
}
if (value.indexOf('-') === (value.length - 1)) {
return;
}
const newVal = Number(value);
if (!isNaN(newVal)) {
this.setCurrentValue(newVal);

View File

@@ -39,14 +39,11 @@ exports.install = Vue => {
if (el.domVisible) {
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;
}
const target = binding.modifiers.fullscreen || binding.modifiers.body
? document.body
: el;
removeClass(target, 'el-loading-parent--relative');
removeClass(target, 'el-loading-parent--hidden');
});
el.instance.visible = false;
}
@@ -59,10 +56,10 @@ exports.install = Vue => {
});
if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed') {
parent.style.position = 'relative';
addClass(parent, 'el-loading-parent--relative');
}
if (binding.modifiers.fullscreen && binding.modifiers.lock) {
parent.style.overflow = 'hidden';
addClass(parent, 'el-loading-parent--hidden');
}
el.domVisible = true;

View File

@@ -1,6 +1,6 @@
import Vue from 'vue';
import loadingVue from './loading.vue';
import { getStyle } from 'element-ui/src/utils/dom';
import { addClass, removeClass, getStyle } from 'element-ui/src/utils/dom';
import merge from 'element-ui/src/utils/merge';
const LoadingConstructor = Vue.extend(loadingVue);
@@ -23,14 +23,11 @@ LoadingConstructor.prototype.close = function() {
fullscreenLoading = undefined;
}
this.$on('after-leave', _ => {
if (this.fullscreen && this.originalOverflow !== 'hidden') {
document.body.style.overflow = this.originalOverflow;
}
if (this.fullscreen || this.body) {
document.body.style.position = this.originalPosition;
} else {
this.target.style.position = this.originalPosition;
}
const target = this.fullscreen || this.body
? document.body
: this.target;
removeClass(target, 'el-loading-parent--relative');
removeClass(target, 'el-loading-parent--hidden');
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el);
}
@@ -88,10 +85,10 @@ const Loading = (options = {}) => {
addStyle(options, parent, instance);
if (instance.originalPosition !== 'absolute' && instance.originalPosition !== 'fixed') {
parent.style.position = 'relative';
addClass(parent, 'el-loading-parent--relative');
}
if (options.fullscreen && options.lock) {
parent.style.overflow = 'hidden';
addClass(parent, 'el-loading-parent--hidden');
}
parent.appendChild(instance.$el);
Vue.nextTick(() => {

View File

@@ -3,6 +3,7 @@ import ElSelect from 'element-ui/packages/select';
import ElOption from 'element-ui/packages/option';
import ElInput from 'element-ui/packages/input';
import Locale from 'element-ui/src/mixins/locale';
import { valueEquals } from 'element-ui/src/utils/util';
export default {
name: 'ElPagination',
@@ -147,9 +148,10 @@ export default {
watch: {
pageSizes: {
immediate: true,
handler(value) {
if (Array.isArray(value)) {
this.$parent.internalPageSize = value.indexOf(this.$parent.pageSize) > -1
handler(newVal, oldVal) {
if (valueEquals(newVal, oldVal)) return;
if (Array.isArray(newVal)) {
this.$parent.internalPageSize = newVal.indexOf(this.$parent.pageSize) > -1
? this.$parent.pageSize
: this.pageSizes[0];
}
@@ -179,8 +181,7 @@ export default {
components: {
ElSelect,
ElOption,
ElInput
ElOption
},
methods: {
@@ -202,6 +203,8 @@ export default {
};
},
components: { ElInput },
methods: {
handleFocus(event) {
this.oldValue = event.target.value;

View File

@@ -26,8 +26,7 @@
<input
type="text"
class="el-select__input"
:class="`is-${ selectSize }`"
@focus="visible = true"
:class="[selectSize ? `is-${ selectSize }` : '']"
:disabled="disabled"
@keyup="managePlaceholder"
@keydown="resetInputState"
@@ -49,6 +48,7 @@
type="text"
:placeholder="currentPlaceholder"
:name="name"
:id="id"
:size="selectSize"
:disabled="disabled"
:readonly="!filterable || multiple"
@@ -113,6 +113,7 @@
import { t } from 'element-ui/src/locale';
import scrollIntoView from 'element-ui/src/utils/scroll-into-view';
import { getValueByPath } from 'element-ui/src/utils/util';
import { valueEquals } from 'element-ui/src/utils/util';
import NavigationMixin from './navigation-mixin';
const sizeMap = {
@@ -121,18 +122,6 @@
'mini': 28
};
const valueEquals = (a, b) => {
// see: https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
if (a === b) return true;
if (!(a instanceof Array)) return false;
if (!(b instanceof Array)) return false;
if (a.length !== b.length) return false;
for (let i = 0; i !== a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
};
export default {
mixins: [Emitter, Locale, Focus('reference'), NavigationMixin],
@@ -208,6 +197,7 @@
props: {
name: String,
id: String,
value: {
required: true
},
@@ -549,7 +539,7 @@
let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0];
const tags = this.$refs.tags;
input.style.height = this.selected.length === 0 && this.selectSize === 'mini'
? sizeMap[this.selectSize]
? sizeMap[this.selectSize] + 'px'
: Math.max(tags ? (tags.clientHeight + 10) : 0, sizeMap[this.selectSize] || 40) + 'px';
if (this.visible && this.emptyText !== false) {
this.broadcast('ElSelectDropdown', 'updatePopper');

View File

@@ -77,6 +77,7 @@ Vue.component('el-table-column', ElTableColumn)
| render-header | 列标题 Label 区域渲染使用的 Function | Function(h, { column, $index }) | — | — |
| sortable | 对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件 | boolean, string | true, false, 'custom' | false |
| sort-method | 对数据进行排序的时候使用的方法,仅当 sortable 设置为 true 的时候有效 | Function(a, b) | — | — |
| sort-by | 对数据进行排序的时候按照 sort-by 排序,仅当 sortable 设置为 true 且没有设置 sort-method 的时候有效。如果 sort-by 为数组,则先按照第 0 个排序,如果第 0 个相等,再按照第 1 个排序,以此类推。 | Function(row, index)/String/Array | — | — |
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | Function(row, column) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | Boolean | — | false |

View File

@@ -134,6 +134,7 @@ export default {
default: false
},
sortMethod: Function,
sortBy: [String, Function, Array],
resizable: {
type: Boolean,
default: true
@@ -234,6 +235,7 @@ export default {
headerAlign: this.headerAlign ? 'is-' + this.headerAlign : (this.align ? 'is-' + this.align : null),
sortable: this.sortable === '' ? true : this.sortable,
sortMethod: this.sortMethod,
sortBy: this.sortBy,
resizable: this.resizable,
showOverflowTooltip: this.showOverflowTooltip || this.showTooltipWhenOverflow,
formatter: this.formatter,

View File

@@ -8,7 +8,7 @@ const sortData = (data, states) => {
if (!sortingColumn || typeof sortingColumn.sortable === 'string') {
return data;
}
return orderBy(data, states.sortProp, states.sortOrder, sortingColumn.sortMethod);
return orderBy(data, states.sortProp, states.sortOrder, sortingColumn.sortMethod, sortingColumn.sortBy);
};
const getKeysMap = function(array, rowKey) {

View File

@@ -345,6 +345,7 @@
this.updateScrollY();
this.layout.update();
this.$nextTick(() => {
if (this.destroyed) return;
if (this.height) {
this.layout.setHeight(this.height);
} else if (this.maxHeight) {
@@ -355,7 +356,7 @@
if (this.$el) {
this.isHidden = this.$el.clientWidth === 0;
if (this.isHidden && this.layout.bodyWidth) {
setTimeout(() => this.doLayout());
setTimeout(() => this.debouncedLayout());
}
}
});
@@ -496,6 +497,7 @@
},
destroyed() {
this.destroyed = true;
if (this.windowResizeListener) removeResizeListener(this.$el, this.windowResizeListener);
},
@@ -536,7 +538,8 @@
resizeProxyVisible: false,
// 是否拥有多级表头
isGroup: false,
scrollPosition: 'left'
scrollPosition: 'left',
destroyed: false
};
}
};

View File

@@ -17,28 +17,61 @@ const isObject = function(obj) {
return obj !== null && typeof obj === 'object';
};
export const orderBy = function(array, sortKey, reverse, sortMethod) {
if (typeof reverse === 'string') {
reverse = reverse === 'descending' ? -1 : 1;
}
if (!sortKey && !sortMethod) {
export const orderBy = function(array, sortKey, reverse, sortMethod, sortBy) {
if (!sortKey && !sortMethod && (!sortBy || Array.isArray(sortBy) && !sortBy.length)) {
return array;
}
const order = (reverse && reverse < 0) ? -1 : 1;
// sort on a copy to avoid mutating original array
return array.slice().sort(sortMethod ? function(a, b) {
const result = sortMethod(a, b);
return result === 0 ? 0 : result > 0 ? order : -order;
} : function(a, b) {
if (sortKey !== '$key') {
if (isObject(a) && '$value' in a) a = a.$value;
if (isObject(b) && '$value' in b) b = b.$value;
if (typeof reverse === 'string') {
reverse = reverse === 'descending' ? -1 : 1;
} else {
reverse = (reverse && reverse < 0) ? -1 : 1;
}
const getKey = sortMethod ? null : function(value, index) {
if (sortBy) {
if (!Array.isArray(sortBy)) {
sortBy = [sortBy];
}
return sortBy.map(function(by) {
if (typeof by === 'string') {
return getValueByPath(value, by);
} else {
return by(value, index, array);
}
});
}
a = isObject(a) ? getValueByPath(a, sortKey) : a;
b = isObject(b) ? getValueByPath(b, sortKey) : b;
return a === b ? 0 : a > b ? order : -order;
});
if (sortKey !== '$key') {
if (isObject(value) && '$value' in value) value = value.$value;
}
return [isObject(value) ? getValueByPath(value, sortKey) : value];
};
const compare = function(a, b) {
if (sortMethod) {
return sortMethod(a.value, b.value);
}
for (let i = 0, len = a.key.length; i < len; i++) {
if (a.key[i] < b.key[i]) {
return -1;
}
if (a.key[i] > b.key[i]) {
return 1;
}
}
return 0;
};
return array.map(function(value, index) {
return {
value: value,
index: index,
key: getKey ? getKey(value, index) : null
};
}).sort(function(a, b) {
let order = compare(a, b);
if (!order) {
// make stable https://en.wikipedia.org/wiki/Sorting_algorithm#Stability
order = a.index - b.index;
}
return order * reverse;
}).map(item => item.value);
};
export const getColumnById = function(table, columnId) {

View File

@@ -33,10 +33,16 @@
return true;
} else {
tabSize = $el[`client${firstUpperCase(sizeName)}`];
if (sizeName === 'width') {
tabSize -= index === 0 ? 20 : 40;
}
return false;
}
});
if (sizeName === 'width' && offset !== 0) {
offset += 20;
}
const transform = `translate${firstUpperCase(sizeDir)}(${offset}px)`;
style[sizeName] = tabSize + 'px';
style.transform = transform;

View File

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

View File

@@ -3,6 +3,7 @@
@import "common/var";
@import "./input.scss";
@import "./scrollbar.scss";
@import "./popper";
@include b(autocomplete) {
position: relative;

View File

@@ -1,6 +1,7 @@
@import "mixins/mixins";
@import "./input.scss";
@import "common/var";
@import "./input.scss";
@import "./popper";
@include b(cascader) {
display: inline-block;

View File

@@ -6,6 +6,7 @@
@include b(checkbox) {
color: $--checkbox-color;
font-weight: $--checkbox-font-weight;
font-size: $--font-size-base;
position: relative;
cursor: pointer;
display: inline-block;
@@ -339,3 +340,7 @@
}
}
}
@include b(checkbox-group) {
font-size: 0;
}

View File

@@ -2,12 +2,12 @@
/* Transition
-------------------------- */
$--all-transition: all .3s cubic-bezier(.645,.045,.355,1);
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
$--fade-linear-transition: opacity 200ms linear;
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1) 100ms, opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) 100ms;
$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1);
$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1);
$--all-transition: all .3s cubic-bezier(.645,.045,.355,1) !default;
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
$--fade-linear-transition: opacity 200ms linear !default;
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1) 100ms, opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) 100ms !default;
$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1) !default;
$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
/* Colors
-------------------------- */

View File

@@ -8,4 +8,5 @@
@import "./date-picker/time-range-picker.scss";
@import "./date-picker/time-picker.scss";
@import "./input.scss";
@import "./scrollbar.scss";
@import "./scrollbar.scss";
@import "./popper";

View File

@@ -15,14 +15,14 @@
@include m((daterange, timerange)) {
&.el-input,
&.el-input__inner {
width: 320px;
width: 350px;
}
}
@include m(datetimerange) {
&.el-input,
&.el-input__inner {
width: 370px;
width: 400px;
}
}
@@ -42,7 +42,7 @@
height: 100%;
margin: 0;
padding: 0;
width: 38%;
width: 39%;
text-align: center;
font-size: $--font-size-base;
color: $--color-text-regular;

View File

@@ -3,7 +3,7 @@
@include b(time-spinner) {
&.has-seconds {
.el-time-spinner__wrapper {
width: 33%;
width: 33.3%;
}
.el-time-spinner__wrapper:nth-child(2) {

View File

@@ -1,6 +1,7 @@
@import "mixins/mixins";
@import "common/var";
@import "button";
@import "./popper";
@include b(dropdown) {
display: inline-block;

View File

@@ -124,14 +124,15 @@
@include when(without-controls) {
.el-input__inner {
padding-left: 15px;
padding-right: 15px;
}
}
@include when(controls-right) {
.el-input__inner {
padding-left: 15px;
padding-right: #{$--input-height + 10};
padding-left: 15px;
padding-right: #{$--input-height + 10};
}
@include e((increase, decrease)) {

View File

@@ -1,6 +1,16 @@
@import "mixins/mixins";
@import "common/var";
@include b(loading-parent) {
@include m(relative) {
position: relative !important;
}
@include m(hidden) {
overflow: hidden !important;
}
}
@include b(loading-mask) {
position: absolute;
z-index: 10000;

View File

@@ -155,7 +155,7 @@
width: 50px;
}
.el-input__inner {
&.el-input .el-input__inner {
height: $--pagination-button-height;
}

View File

@@ -1,5 +1,6 @@
@import "mixins/mixins";
@import "common/var";
@import "./popper";
@include b(popover) {
position: absolute;
@@ -27,102 +28,3 @@
margin-bottom: 12px;
}
}
@include b(popper) {
.popper__arrow,
.popper__arrow::after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.popper__arrow {
border-width: $--popover-arrow-size;
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03))
}
.popper__arrow::after {
content: " ";
border-width: $--popover-arrow-size;
}
&[x-placement^="top"] {
margin-bottom: #{$--popover-arrow-size + 6};
}
&[x-placement^="top"] .popper__arrow {
bottom: -$--popover-arrow-size;
left: 50%;
margin-right: #{$--tooltip-arrow-size / 2};
border-top-color: $--popover-border-color;
border-bottom-width: 0;
&::after {
bottom: 1px;
margin-left: -$--popover-arrow-size;
border-top-color: $--popover-fill;
border-bottom-width: 0;
}
}
&[x-placement^="bottom"] {
margin-top: #{$--popover-arrow-size + 6};
}
&[x-placement^="bottom"] .popper__arrow {
top: -$--popover-arrow-size;
left: 50%;
margin-right: #{$--tooltip-arrow-size / 2};
border-top-width: 0;
border-bottom-color: $--popover-border-color;
&::after {
top: 1px;
margin-left: -$--popover-arrow-size;
border-top-width: 0;
border-bottom-color: $--popover-fill;
}
}
&[x-placement^="right"] {
margin-left: #{$--popover-arrow-size + 6};
}
&[x-placement^="right"] .popper__arrow {
top: 50%;
left: -$--popover-arrow-size;
margin-bottom: #{$--tooltip-arrow-size / 2};
border-right-color: $--popover-border-color;
border-left-width: 0;
&::after {
bottom: -$--popover-arrow-size;
left: 1px;
border-right-color: $--popover-fill;
border-left-width: 0;
}
}
&[x-placement^="left"] {
margin-right: #{$--popover-arrow-size + 6};
}
&[x-placement^="left"] .popper__arrow {
top: 50%;
right: -$--popover-arrow-size;
margin-bottom: #{$--tooltip-arrow-size / 2};
border-right-width: 0;
border-left-color: $--popover-border-color;
&::after {
right: 1px;
bottom: -$--popover-arrow-size;
margin-left: -$--popover-arrow-size;
border-right-width: 0;
border-left-color: $--popover-fill;
}
}
}

View File

@@ -0,0 +1,101 @@
@import "mixins/mixins";
@import "common/var";
@include b(popper) {
.popper__arrow,
.popper__arrow::after {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.popper__arrow {
border-width: $--popover-arrow-size;
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03))
}
.popper__arrow::after {
content: " ";
border-width: $--popover-arrow-size;
}
&[x-placement^="top"] {
margin-bottom: #{$--popover-arrow-size + 6};
}
&[x-placement^="top"] .popper__arrow {
bottom: -$--popover-arrow-size;
left: 50%;
margin-right: #{$--tooltip-arrow-size / 2};
border-top-color: $--popover-border-color;
border-bottom-width: 0;
&::after {
bottom: 1px;
margin-left: -$--popover-arrow-size;
border-top-color: $--popover-fill;
border-bottom-width: 0;
}
}
&[x-placement^="bottom"] {
margin-top: #{$--popover-arrow-size + 6};
}
&[x-placement^="bottom"] .popper__arrow {
top: -$--popover-arrow-size;
left: 50%;
margin-right: #{$--tooltip-arrow-size / 2};
border-top-width: 0;
border-bottom-color: $--popover-border-color;
&::after {
top: 1px;
margin-left: -$--popover-arrow-size;
border-top-width: 0;
border-bottom-color: $--popover-fill;
}
}
&[x-placement^="right"] {
margin-left: #{$--popover-arrow-size + 6};
}
&[x-placement^="right"] .popper__arrow {
top: 50%;
left: -$--popover-arrow-size;
margin-bottom: #{$--tooltip-arrow-size / 2};
border-right-color: $--popover-border-color;
border-left-width: 0;
&::after {
bottom: -$--popover-arrow-size;
left: 1px;
border-right-color: $--popover-fill;
border-left-width: 0;
}
}
&[x-placement^="left"] {
margin-right: #{$--popover-arrow-size + 6};
}
&[x-placement^="left"] .popper__arrow {
top: 50%;
right: -$--popover-arrow-size;
margin-bottom: #{$--tooltip-arrow-size / 2};
border-right-width: 0;
border-left-color: $--popover-border-color;
&::after {
right: 1px;
bottom: -$--popover-arrow-size;
margin-left: -$--popover-arrow-size;
border-right-width: 0;
border-left-color: $--popover-fill;
}
}
}

View File

@@ -5,4 +5,5 @@
display: inline-block;
line-height: 1;
vertical-align: middle;
font-size: 0;
}

View File

@@ -12,6 +12,7 @@
display: inline-block;
white-space: nowrap;
outline: none;
font-size: $--font-size-base;
@include utils-user-select(none);
@include when(bordered) {

View File

@@ -1,5 +1,6 @@
@import "mixins/mixins";
@import "common/var";
@import "./popper";
@include b(select-dropdown) {
position: absolute;

View File

@@ -206,6 +206,12 @@
bottom: 0;
left: 11px;
}
@include e(icon) {
@include when(icon) {
width: 24px;
}
}
}
@include when(center) {
@@ -244,10 +250,6 @@
width: 16px;
height: 16px;
font-size: 12px;
@include when(icon) {
width: 30px;
}
}
@include e(icon-inner) {

View File

@@ -224,6 +224,11 @@
}
}
}
@include m((top, bottom)) {
&:not(.el-tabs--border-card):not(.el-tabs--card) .el-tabs__item:nth-child(2) {
padding-left: 0;
}
}
@include m(bottom) {
.el-tabs__header {
margin-bottom: 0;

View File

@@ -3,3 +3,4 @@
@import "./date-picker/time-picker.scss";
@import "./input.scss";
@import "./scrollbar.scss";
@import "./popper";

View File

@@ -1,7 +1,8 @@
@import "common/var";
@import "./date-picker/picker.scss";
@import "./date-picker/date-picker.scss";
@import "common/var";
@import "./scrollbar.scss";
@import "./popper";
.time-select {
margin: 5px 0;

View File

@@ -33,7 +33,7 @@
cursor: pointer;
& > .el-tree-node__expand-icon {
margin: 0 8px;
padding: 6px;
}
& > .el-checkbox {
margin-right: 8px;
@@ -45,13 +45,8 @@
@include e(expand-icon) {
cursor: pointer;
width: 0;
height: 0;
margin-left: 10px;
border: 3.5px solid transparent;
border-right-width: 0;
border-left-color: $--tree-expand-icon-color;
border-left-width: 6px;
color: $--tree-expand-icon-color;
font-size: 12px;
transform: rotate(0deg);
transition: transform 0.3s ease-in-out;
@@ -61,7 +56,7 @@
}
&.is-leaf {
border-color: transparent;
color: transparent;
cursor: default;
}
}

View File

@@ -330,7 +330,12 @@
font-size: 20px;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s;
@include utils-vertical-center;
&::after {
display: inline-block;
content: "";
height: 100%;
vertical-align: middle
}
span {
display: none;

View File

@@ -54,6 +54,7 @@ export default class TreeStore {
node.visible = allHidden === false;
}
}
if (!value) return;
if (node.visible && !node.isLeaf) node.expand();
};

View File

@@ -10,7 +10,7 @@
<div class="el-tree-node__content"
:style="{ 'padding-left': (node.level - 1) * tree.indent + 'px' }">
<span
class="el-tree-node__expand-icon"
class="el-tree-node__expand-icon el-icon-caret-right"
@click.stop="handleExpandIconClick"
:class="{ 'is-leaf': node.isLeaf, expanded: !node.isLeaf && expanded }">
</span>

View File

@@ -41,20 +41,20 @@
:stroke-width="listType === 'picture-card' ? 6 : 2"
:percentage="parsePercentage(file.percentage)">
</el-progress>
<span class="el-upload-list__item-actions" v-if="listType === 'picture-card'">
<span class="el-upload-list__item-actions" v-if="listType === 'picture-card'">
<span
class="el-upload-list__item-preview"
v-if="handlePreview && listType === 'picture-card'"
@click="handlePreview(file)"
>
<i class="el-icon-view"></i>
<i class="el-icon-zoom-in"></i>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="$emit('remove', file)"
>
<i class="el-icon-delete2"></i>
<i class="el-icon-delete"></i>
</span>
</span>
</li>

View File

@@ -13,7 +13,8 @@ export default {
interval = null;
};
on(el, 'mousedown', () => {
on(el, 'mousedown', (e) => {
if (e.button !== 0) return;
startTime = new Date();
once(document, 'mouseup', clear);
clearInterval(interval);

View File

@@ -173,7 +173,7 @@ if (typeof window !== 'undefined' && window.Vue) {
};
module.exports = {
version: '2.0.0-rc.1',
version: '2.0.2',
locale: locale.use,
i18n: locale.i18n,
install,

View File

@@ -49,6 +49,7 @@ export function getPropByPath(obj, path, strict) {
let keyArr = path.split('.');
let i = 0;
for (let len = keyArr.length; i < len - 1; ++i) {
if (!tempObj && !strict) break;
let key = keyArr[i];
if (key in tempObj) {
tempObj = tempObj[key];
@@ -62,7 +63,7 @@ export function getPropByPath(obj, path, strict) {
return {
o: tempObj,
k: keyArr[i],
v: tempObj[keyArr[i]]
v: tempObj ? tempObj[keyArr[i]] : null
};
};
@@ -70,3 +71,14 @@ export const generateId = function() {
return Math.floor(Math.random() * 10000);
};
export const valueEquals = (a, b) => {
// see: https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript
if (a === b) return true;
if (!(a instanceof Array)) return false;
if (!(b instanceof Array)) return false;
if (a.length !== b.length) return false;
for (let i = 0; i !== a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
};

View File

@@ -101,13 +101,14 @@ describe('DatePicker', () => {
setTimeout(_ => {
const $el = vm.$refs.compo.picker.$el;
$el.querySelector('td.available').click();
vm.$nextTick(_ => {
vm.$el.querySelector('.el-input__icon').click();
setTimeout(_ => {
vm.$refs.compo.showClose = true;
vm.$refs.compo.handleClickIcon({ stopPropagation: () => null });
setTimeout(_ => {
expect(vm.value).to.empty;
expect(vm.value).to.equal(null);
done();
}, DELAY);
});
}, DELAY);
}, DELAY);
});
@@ -1175,6 +1176,28 @@ describe('DatePicker', () => {
done();
}, DELAY);
});
it('clear value', done => {
vm = createVue({
template: '<el-date-picker type="daterange" v-model="value" ref="compo" />',
data() {
return {
value: [new Date(2000, 9, 1), new Date(2000, 9, 2)]
};
}
}, true);
vm.$el.querySelector('input').focus();
setTimeout(_ => {
vm.$refs.compo.showClose = true;
vm.$refs.compo.handleClickIcon({ stopPropagation: () => null });
setTimeout(_ => {
expect(vm.value).to.equal(null);
done();
}, DELAY);
}, DELAY);
});
});
describe('type:datetimerange', () => {

View File

@@ -1,5 +1,7 @@
import { createVue, triggerEvent, triggerClick, destroyVM } from '../util';
const DELAY = 1;
describe('InputNumber', () => {
let vm;
afterEach(() => {
@@ -263,30 +265,51 @@ describe('InputNumber', () => {
});
});
});
it('event:change', done => {
vm = createVue({
template: `
<el-input-number v-model="value" ref="input">
</el-input-number>
`,
data() {
return {
value: 1.5
};
}
}, true);
describe('event:change', () => {
let spy;
let btnIncrease = vm.$el.querySelector('.el-input-number__increase');
const spy = sinon.spy();
beforeEach(() => {
vm = createVue({
template: `
<el-input-number v-model="value" ref="compo" :min='2' :max='3' :step='1'>
</el-input-number>
`,
data() {
return {
value: 2
};
}
}, true);
spy = sinon.spy();
vm.$refs.compo.$on('change', spy);
});
vm.$refs.input.$on('change', spy);
it('emit on input', done => {
vm.$refs.compo.handleInput('3');
setTimeout(_ => {
expect(spy.calledOnce).to.be.true;
expect(spy.args[0][0]).to.equal(3);
done();
}, DELAY);
});
triggerEvent(btnIncrease, 'mousedown');
triggerClick(document, 'mouseup');
it('emit on button', done => {
const btnIncrease = vm.$el.querySelector('.el-input-number__increase');
triggerEvent(btnIncrease, 'mousedown');
triggerClick(document, 'mouseup');
setTimeout(_ => {
expect(spy.calledOnce).to.be.true;
expect(spy.args[0][0]).to.equal(3);
done();
}, DELAY);
});
vm.$nextTick(_ => {
expect(spy.withArgs(2.5, 1.5).calledOnce).to.be.true;
done();
it('does not emit on programatic change', done => {
vm.value = 3;
setTimeout(_ => {
expect(spy.notCalled).to.be.true;
done();
}, DELAY);
});
});
it('event:focus & blur', done => {

View File

@@ -1,3 +1,4 @@
import { getStyle } from '../../../src/utils/dom';
import { createVue, destroyVM } from '../util';
import Vue from 'vue';
import LoadingRaw from 'packages/loading';
@@ -142,7 +143,7 @@ describe('Loading', () => {
}
}, true);
Vue.nextTick(() => {
expect(document.body.style.overflow).to.equal('hidden');
expect(getStyle(document.body, 'overflow')).to.equal('hidden');
vm.loading = false;
document.body.removeChild(document.querySelector('.el-loading-mask'));
document.body.removeChild(vm.$el);
@@ -197,7 +198,7 @@ describe('Loading', () => {
expect(mask.parentNode).to.equal(container);
loadingInstance.close();
setTimeout(() => {
expect(container.style.position).to.equal('relative');
expect(getStyle(container, 'position')).to.equal('relative');
done();
}, 200);
});
@@ -243,7 +244,7 @@ describe('Loading', () => {
it('lock', () => {
loadingInstance = Loading({ lock: true });
expect(document.body.style.overflow).to.equal('hidden');
expect(getStyle(document.body, 'overflow')).to.equal('hidden');
});
it('text', () => {

View File

@@ -995,7 +995,14 @@ describe('Table', () => {
'sortable :sort-method="sortMethod"', '', '', '', {
methods: {
sortMethod(a, b) {
return a.runtime < b.runtime;
// sort method should return number
if (a.runtime < b.runtime) {
return 1;
}
if (a.runtime > b.runtime) {
return -1;
}
return 0;
}
}
});
@@ -1013,6 +1020,46 @@ describe('Table', () => {
}, DELAY);
});
it('sortable by method', done => {
const vm = createTable(
'sortable :sort-by="sortBy"', '', '', '', {
methods: {
sortBy(a) {
return -a.runtime;
}
}
});
setTimeout(_ => {
const elm = vm.$el.querySelector('.caret-wrapper');
elm.click();
setTimeout(_ => {
const lastCells = vm.$el.querySelectorAll('.el-table__body-wrapper tbody tr td:last-child');
expect(toArray(lastCells).map(node => node.textContent)).to.eql(['100', '95', '92', '92', '80']);
destroyVM(vm);
done();
}, DELAY);
}, DELAY);
});
it('sortable by property', done => {
const vm = createTable(
'sortable sort-by="runtime"', '', '', '', {});
setTimeout(_ => {
const elm = vm.$el.querySelector('.caret-wrapper');
elm.click();
setTimeout(_ => {
const lastCells = vm.$el.querySelectorAll('.el-table__body-wrapper tbody tr td:last-child');
expect(toArray(lastCells).map(node => node.textContent)).to.eql(['80', '92', '92', '95', '100']);
destroyVM(vm);
done();
}, DELAY);
}, DELAY);
});
it('sort-change', done => {
let result;
const vm = createTable('sortable="custom"', '', '', '', {

8
types/carousel.d.ts vendored
View File

@@ -36,18 +36,18 @@ export declare class ElCarousel extends ElementUIComponent {
*
* @param index Index of the slide to be switched to (starting from 0)
*/
setActiveItem (index: number)
setActiveItem (index: number): void
/**
* Manually switch slide by carousel item's name
*
* @param name The name of the corresponding `el-carousel-item`
*/
setActiveItem (name: string)
setActiveItem (name: string): void
/** Switch to the previous slide */
prev ()
prev (): void
/** Switch to the next slide */
next ()
next (): void
}

View File

@@ -3,7 +3,7 @@ import Vue from 'vue'
/** ElementUI component common definition */
export declare class ElementUIComponent extends Vue {
/** Install component into Vue */
static install (vue: typeof Vue)
static install (vue: typeof Vue): void
}
/** Component size definition for button, input, etc */

4
types/index.d.ts vendored
View File

@@ -77,7 +77,7 @@ declare namespace ElementUI {
* Please do not invoke this method directly.
* Call `Vue.use(ElementUI)` to install.
*/
export function install (vue: typeof Vue, options: ElementUI.InstallationOptions)
export function install (vue: typeof Vue, options: ElementUI.InstallationOptions): void
/** ElementUI component common definition */
export type Component = ElementUIComponent
@@ -283,4 +283,4 @@ declare namespace ElementUI {
export class Upload extends ElUpload {}
}
export = ElementUI
export default ElementUI

4
types/loading.d.ts vendored
View File

@@ -30,7 +30,7 @@ export interface LoadingServiceOptions {
/** Loading Component */
export declare class ElLoadingComponent extends Vue {
/** Close the Loading instance */
close ()
close (): void
}
/** Loading directive definition */
@@ -46,7 +46,7 @@ export interface ElLoadingDirective extends VNodeDirective {
/** Show animation while loading data */
export interface ElLoading {
/** Install Loading directive into Vue */
install (vue: typeof Vue)
install (vue: typeof Vue): void
/** If you do not have a specific DOM node to attach the Loading directive, or if you simply prefer not to use Loading as a directive, you can call this service with some configs to open a Loading instance. */
service (options: LoadingServiceOptions): ElLoadingComponent

View File

@@ -139,10 +139,10 @@ export interface ElMessageBox {
prompt: ElMessageBoxShortcutMethod
/** Set default options of message boxes */
setDefaults (defaults: ElMessageBoxOptions)
setDefaults (defaults: ElMessageBoxOptions): void
/** Close current message box */
close ()
close (): void
}
declare module 'vue/types/vue' {

2
types/message.d.ts vendored
View File

@@ -5,7 +5,7 @@ export type MessageType = 'success' | 'warning' | 'info' | 'error'
/** Message Component */
export declare class ElMessageComponent extends Vue {
/** Close the Loading instance */
close ()
close (): void
}
export interface CloseEventHandler {

View File

@@ -4,7 +4,7 @@ import { MessageType } from './message'
/** Notification Component */
export declare class ElNotificationComponent extends Vue {
/** Close the Notification instance */
close ()
close (): void
}
export interface ElNotificationOptions {

5
types/tree.d.ts vendored
View File

@@ -1,6 +1,5 @@
import { CreateElement, VNode } from 'vue'
import { ElementUIComponent } from './component'
import {Tree} from "./index";
/** The node of the tree */
export interface TreeNode {
@@ -46,7 +45,7 @@ export declare class ElTree extends ElementUIComponent {
props: object
/** Method for loading subtree data */
load: (node: TreeNode, resolve) => void
load: (node: TreeNode, resolve: Function) => void
/** Render function for tree node */
renderContent: RenderContent
@@ -128,7 +127,7 @@ export declare class ElTree extends ElementUIComponent {
* @param checked Indicating the node checked or not
* @param deep Indicating whether to checked state deeply or not
*/
setChecked (data: TreeNode | any, checked: boolean, deep: boolean)
setChecked (data: TreeNode | any, checked: boolean, deep: boolean): void
/**
* Return the highlight node's key (null if no node is highlighted)