Merge pull request #2036 from ElemeFE/1.1

1.1
pull/2046/head
杨奕 2016-12-28 15:32:24 +08:00 committed by GitHub
commit 7f35ee1423
113 changed files with 3460 additions and 364 deletions

View File

@ -1,18 +1,10 @@
sudo: false
language: node_js
node_js: stable
cache:
directories:
- $HOME/.npm
- $HOME/.yarn-cache
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash
- export PATH=$HOME/.yarn/bin:$PATH
- export TRAVIS_COMMIT_MSG="[deploy] $(git log --format='%h - %B' --no-merges -n 1)"
- export TRAVIS_COMMIT_USER="$(git log --no-merges -n 1 --format=%an)"
- export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)"
install: yarn install
script: yarn run test
after_success:
- sh build/deploy-ci.sh
- cat ./test/unit/coverage/lcov.info | ./node_modules/.bin/coveralls

View File

@ -33,6 +33,7 @@ export default ${ComponentName};`
filename: 'cooking.conf.js',
content: `var cooking = require('cooking');
var path = require('path');
var config = require('../../build/config');
cooking.set({
entry: {
@ -52,7 +53,7 @@ module.exports = cooking.resolve();`
{
filename: 'package.json',
content: `{
"name": "el-${componentname}",
"name": "element-${componentname}",
"version": "0.0.0",
"description": "A ${componentname} component for Vue.js.",
"keywords": [
@ -75,7 +76,7 @@ module.exports = cooking.resolve();`
<script>
export default {
name: 'el-${componentname}'
name: 'El${ComponentName}'
};
</script>`
},
@ -90,16 +91,16 @@ export default {
{
filename: path.join('../../test/unit/specs', `${componentname}.spec.js`),
content: `import { createTest, destroyVM } from '../util';
import Alert from 'packages/{{componentname}}';
import ${ComponentName} from 'packages/${componentname}';
describe('{{ComponentName}}', () => {
describe('${ComponentName}', () => {
let vm;
afterEach(() => {
destroyVM(vm);
});
it('create', () => {
vm = createTest({{ComponentName}}, true);
vm = createTest(${ComponentName}, true);
expect(vm.$el).to.exist;
});
});

View File

@ -8,7 +8,7 @@ cooking.set({
extends: process.env.CI_ENV ? ['vue2'] : ['vue2', 'lint'],
minimize: false,
alias: Object.assign(config.alias, {
'vue$': 'vue/dist/vue.js'
'vue$': 'vue/dist/vue.common.js'
}),
postcss: function(webapck) {
return [

View File

@ -42,7 +42,7 @@ if [ "$TRAVIS_TAG" ]; then
export SUB_FOLDER=$(echo "$TRAVIS_TAG" | grep -o -E "\d+\.\d+")
echo $SUB_FOLDER
SUB_FOLDER='1.0'
SUB_FOLDER='1.1'
mkdir $SUB_FOLDER
rm -rf *.js *.css *.map static
rm -rf $SUB_FOLDER/**

View File

@ -53,5 +53,10 @@
"card": "./packages/card/index.js",
"rate": "./packages/rate/index.js",
"steps": "./packages/steps/index.js",
"step": "./packages/step/index.js"
"step": "./packages/step/index.js",
"carousel": "./packages/carousel/index.js",
"scrollbar": "./packages/scrollbar/index.js",
"carousel-item": "./packages/carousel-item/index.js",
"collapse": "./packages/collapse/index.js",
"collapse-item": "./packages/collapse-item/index.js"
}

View File

@ -1,5 +1,5 @@
<script>
import { addClass } from 'wind-dom/src/class';
import { addClass } from 'element-ui/src/utils/dom';
export default {
data() {
return {
@ -78,7 +78,7 @@ Different colors represent different meanings.
```
:::
### Icon Button
### Icon Button
Use icons to add more meaning to Button. You can use icon alone to save some space, or with text together.

View File

@ -0,0 +1,189 @@
<script>
export default {
mounted() {
this.$nextTick(() => {
const demos = document.querySelectorAll('.source');
demos[0].style.padding = '0';
demos[0].className += ' small';
demos[3].className += ' medium';
});
}
}
</script>
## Carousel
Loop a series of images or texts in a limited space
### Basic usage
::: demo Combine `el-carousel` with `el-carousel-item`, and you'll get a carousel. Content of each slide is completely customizable, and you just need to place it inside `el-carousel-item` tag. By default the carousel switches when mouse hovers over an indicator. Set `trigger` to `click`, and the carousel switches only when an indicator is clicked.
```html
<template>
<div class="block">
<span class="demonstration">Switch when indicator is hovered (default)</span>
<el-carousel height="150px">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</div>
<div class="block">
<span class="demonstration">Switch when indicator is clicked</span>
<el-carousel trigger="click" height="150px">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</div>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### Indicators
Indicators can be displayed outside the carousel
::: demo The `indicator-position` attribute determines where the indicators are located. By default they are inside the carousel, and setting `indicator-position` to `outside` moves them outside; setting `indicator-position` to `none` hides the indicators.
```html
<template>
<el-carousel indicator-position="outside">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### Arrows
You can define when arrows are displayed
::: demo The `arrow` attribute determines when arrows are displayed. By default they appear when mouse hovers over the carousel. Setting `arrow` to `always` or `never` shows/hides the arrows permanently.
```html
<template>
<el-carousel :interval="5000" arrow="always">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### Card mode
When a page is wide enough but has limited height, you can activate card mode for carousels
::: demo Setting `type` to `card` activates the card mode. Apart from the appearance, the biggest difference between card mode and common mode is that clicking the slides at both sides directly switches the carousel in card mode.
```html
<template>
<el-carousel :interval="4000" type="card" height="200px">
<el-carousel-item v-for="item in 6">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 200px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### Carousel Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| height | height of the carousel | number | — | 300 |
| initial-index | index of the initially active slide (starting from 0) | number | — | 0 |
| trigger | how indicators are triggered | string | click | — |
| autoplay | whether automatically loop the slides | boolean | — | true |
| interval | interval of the auto loop, in milliseconds | number | — | 3000 |
| indicator-position | position of the indicators | string | outside/none | — |
| arrow | when arrows are shown | string | always/hover/never | hover |
| type | type of the Carousel | string | card | — |
### Events
| Event Name | Description | Parameters |
|---------|---------|---------|
| change | triggers when the active slide switches | index of the new active slide, index of the old active slide |
### Methods
| Method | Description | Parameters |
|---------- |-------------- | - |
| setActiveItem | manually switch slide | index of the slide to be switched to, starting from 0; or the `name` of corresponding `el-carousel-item` |
| prev | switch to the previous slide | — |
| next | switch to the next slide | — |
### Carousel-Item Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| name | name of the item, can be used in `setActiveItem` | string | — | — |

View File

@ -40,7 +40,7 @@ Checkbox can be used alone to switch between two states.
```
:::
## Disabled State
### Disabled State
Disabled state for checkbox.

View File

@ -0,0 +1,141 @@
<script>
export default {
data() {
return {
activeNames: ['1'],
activeName: '1'
};
},
methods: {
handleChange(val) {
console.log(val);
}
}
}
</script>
## Collapse
Use Collapse to store contents.
### Basic usage
You can expand multiple panels
:::demo
```html
<el-collapse v-model="activeNames" @change="handleChange">
<el-collapse-item title="Consistency" name="1">
<div>Consistent with real life: in line with the process and logic of real life, and comply with languages and habits that the users are used to;</div>
<div>Consistent within interface: all elements should be consistent, such as: design style, icons and texts, position of elements, etc.</div>
</el-collapse-item>
<el-collapse-item title="Feedback" name="2">
<div>Operation feedback: enable the users to clearly perceive their operations by style updates and interactive effects;</div>
<div>Visual feedback: reflect current state by updating or rearranging elements of the page.</div>
</el-collapse-item>
<el-collapse-item title="Efficiency" name="3">
<div>Simplify the process: keep operating process simple and intuitive;</div>
<div>Definite and clear: enunciate your intentions clearly so that the users can quickly understand and make decisions;</div>
<div>Easy to identify: the interface should be straightforward, which helps the users to identify and frees them from memorizing and recalling.</div>
</el-collapse-item>
<el-collapse-item title="Controllability" name="4">
<div>Decision making: giving advices about operations is acceptable, but do not make decisions for the users;</div>
<div>Controlled consequences: users should be granted the freedom to operate, including canceling, aborting or terminating current operation.</div>
</el-collapse-item>
</el-collapse>
<script>
export default {
data() {
return {
activeNames: ['1']
};
}
}
</script>
```
:::
### Accordion
In accordion mode, only one panel can be expanded at once
:::demo Activate accordion mode using the `accordion` attribute.
```html
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="Consistency" name="1">
<div>Consistent with real life: in line with the process and logic of real life, and comply with languages and habits that the users are used to;</div>
<div>Consistent within interface: all elements should be consistent, such as: design style, icons and texts, position of elements, etc.</div>
</el-collapse-item>
<el-collapse-item title="Feedback" name="2">
<div>Operation feedback: enable the users to clearly perceive their operations by style updates and interactive effects;</div>
<div>Visual feedback: reflect current state by updating or rearranging elements of the page.</div>
</el-collapse-item>
<el-collapse-item title="Efficiency" name="3">
<div>Simplify the process: keep operating process simple and intuitive;</div>
<div>Definite and clear: enunciate your intentions clearly so that the users can quickly understand and make decisions;</div>
<div>Easy to identify: the interface should be straightforward, which helps the users to identify and frees them from memorizing and recalling.</div>
</el-collapse-item>
<el-collapse-item title="Controllability" name="4">
<div>Decision making: giving advices about operations is acceptable, but do not make decisions for the users;</div>
<div>Controlled consequences: users should be granted the freedom to operate, including canceling, aborting or terminating current operation.</div>
</el-collapse-item>
</el-collapse>
<script>
export default {
data() {
return {
activeName: '1'
};
}
}
</script>
```
:::
### Custom title
Besides using the `title` attribute, you can customize panel title with scoped slots, which makes adding custom content, e.g. icons, possible.
:::demo
```html
<el-collapse accordion>
<el-collapse-item title="Consistency" name="1">
<template slot="title" scope="props">
{{props.title}}<i class="header-icon el-icon-information"></i>
</template>
<div>Consistent with real life: in line with the process and logic of real life, and comply with languages and habits that the users are used to;</div>
<div>Consistent within interface: all elements should be consistent, such as: design style, icons and texts, position of elements, etc.</div>
</el-collapse-item>
<el-collapse-item title="Feedback" name="2">
<div>Operation feedback: enable the users to clearly perceive their operations by style updates and interactive effects;</div>
<div>Visual feedback: reflect current state by updating or rearranging elements of the page.</div>
</el-collapse-item>
<el-collapse-item title="Efficiency" name="3">
<div>Simplify the process: keep operating process simple and intuitive;</div>
<div>Definite and clear: enunciate your intentions clearly so that the users can quickly understand and make decisions;</div>
<div>Easy to identify: the interface should be straightforward, which helps the users to identify and frees them from memorizing and recalling.</div>
</el-collapse-item>
<el-collapse-item title="Controllability" name="4">
<div>Decision making: giving advices about operations is acceptable, but do not make decisions for the users;</div>
<div>Controlled consequences: users should be granted the freedom to operate, including canceling, aborting or terminating current operation.</div>
</el-collapse-item>
</el-collapse>
```
:::
### Collapse Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| accordion | whether to activate accordion mode | boolean | — | false |
| value | currently active panel | string (accordion mode)/array (non-accordion mode) | — | — |
### Collapse Events
| Event Name | Description | Parameters |
|---------|---------|---------|
| change | triggers when active panels change | activeNames: array (non-accordion mode)/string (accordion mode) |
### Collapse Item Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| name | unique identification of the panel | string/number | — | — |
| title | title of the panel | string | — | — |

View File

@ -269,6 +269,7 @@ Picking a date range is supported.
|---------- |-------------- |---------- |-------------------------------- |-------- |
| shortcuts | a { text, onClick } object array to set shortcut options, check the table below | object[] | — | — |
| disabledDate | a function determining if a date is disabled with that date as its parameter. Should return a Boolean | function | — | — |
| firstDayOfWeek | first day of week | Number | 1 to 7 | 7 |
### shortcuts
| Attribute | Description | Type | Accepted Values | Default |

View File

@ -809,11 +809,11 @@ Form component allows you to verify your data, helping you find and correct erro
### Form Methods
| Method | Description |
| ---- | ---- |
| validate(cb) | the method to validate the whole form |
| validateField(prop, cb) | the method to validate a certain form item |
| resetFields | reset all the fields to initial value and remove validation result |
| Method | Description | Parameters |
| ---- | ---- | ---- |
| validate | the method to validate the whole form | Function(callback: Function(boolean)) |
| validateField | the method to validate a certain form item | Function(prop: string, callback: Function(errorMessage: string)) |
| resetFields | reset all the fields and remove validation result | — |
### Form-Item Attributes

View File

@ -1,4 +1,4 @@
## Pagination
## Pagination
If you have too much data to display in one page, use pagination.
@ -117,7 +117,7 @@ Add more modules based on your scenario.
```
:::
<script>
import { addClass } from 'wind-dom/src/class';
import { addClass } from 'element-ui/src/utils/dom';
export default {
data() {
return {

View File

@ -45,7 +45,7 @@ Typical configurations for these config files are:
},
"dependencies": {
"element-ui": "^1.0.0",
"vue": "^2.0.5"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-core": "^6.0.0",

View File

@ -568,15 +568,13 @@ When there are too many columns, you can fix some of them.
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="Operations"
width="120">
<span>
<template scope="scope">
<el-button @click="handleClick" type="text" size="small">Detail</el-button>
<el-button type="text" size="small">Edit</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -781,19 +779,17 @@ When the the data is dynamically changed, you might want the table to have a max
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="Operations"
width="120">
<span>
<template scope="scope">
<el-button
@click.native.prevent="deleteRow($index, tableData4)"
@click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text"
size="small">
Remove
</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -1045,13 +1041,12 @@ Single row selection is supported.
You can also select multiple rows.
:::demo Activating multiple selection is easy: simply add an `el-table-column` with its `type` set to `selection`. Apart from multiple selection, this example also uses `inline-template` and `show-overflow-tooltip`: when the attribute `inline-template` is set, you can use custom template inside `el-table-column`, and access current row data via `row`; by default, if the content is too long, it will break into multiple lines. If you want to keep it in one line, use attribute `show-overflow-tooltip`, which accepts a `Boolean` value. When set `true`, the extra content will show in tooltip when hover on the cell.
:::demo Activating multiple selection is easy: simply add an `el-table-column` with its `type` set to `selection`. Apart from multiple selection, this example also uses `show-overflow-tooltip`: by default, if the content is too long, it will break into multiple lines. If you want to keep it in one line, use attribute `show-overflow-tooltip`, which accepts a `Boolean` value. When set `true`, the extra content will show in tooltip when hover on the cell.
```html
<template>
<el-table
:data="tableData3"
border
selection-mode="multiple"
style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column
@ -1059,10 +1054,9 @@ You can also select multiple rows.
width="55">
</el-table-column>
<el-table-column
inline-template
label="Date"
width="120">
<div>{{ row.date }}</div>
<template scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
property="name"
@ -1219,9 +1213,12 @@ Filter the table to find desired data.
label="Tag"
width="100"
:filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]"
:filter-method="filterTag"
inline-template>
<el-tag :type="row.tag === 'Home' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag>
:filter-method="filterTag">
<template scope="scope">
<el-tag
:type="scope.row.tag === 'Home' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
@ -1269,7 +1266,7 @@ Filter the table to find desired data.
### Custom column template
Customize table column so it can be integrated with other components.
:::demo Activate custom column template by adding the `inline-template` attribute. By default, the context of `el-table-column` is the one where `el-table` lies, and you can customize it with the `context` attribute, e.g. `:context="_self"` refers to the current context. This is useful when sometimes Table is encapsulated into another component, and `table-column` is distributed by slots. In `el-column`, you have access to the following data: row, column, $index and store (state management of Table).
:::demo You have access to the following data: row, column, $index and store (state management of Table) by [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots). (Scoped slots is supported from `1.1`, `inline-template` still works, but it's not recommended).
```html
<template>
<el-table
@ -1277,43 +1274,38 @@ Customize table column so it can be integrated with other components.
border
style="width: 100%">
<el-table-column
inline-template
label="Date"
width="180">
<div>
<template scope="scope">
<el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span>
</div>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column
inline-template
label="Name"
width="180">
<el-popover trigger="hover" placement="top">
<p>Name: {{ row.name }}</p>
<p>Addr: {{ row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag>
</div>
</el-popover>
<template scope="scope">
<el-popover trigger="hover" placement="top">
<p>Name: {{ scope.row.name }}</p>
<p>Addr: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
:context="_self"
inline-template
label="Operations">
<div>
<template scope="scope">
<el-button
size="small"
@click="handleEdit($index, row)">
Edit
</el-button>
@click="handleEdit(scope.$index, scope.row)">Edit</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete($index, row)">
Delete
</el-button>
</div>
@click="handleDelete(scope.$index, scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
</template>
@ -1460,6 +1452,7 @@ When the row content is too long and you do not want to display the horizontal s
| empty-text | Displayed text when data is empty. You can customize this area with `slot="empty"` | String | - | No Data |
| default-expand-all | whether expand all rows by default, only works when the table has a column type="expand" | Boolean | - | false |
| expand-row-keys | set expanded rows by this prop, prop's value is the keys of expand rows, you should set row-key before using this prop | Array | - | |
| virtual-scrollbar | Enable virtual scrollbar | Boolean | - | false |
### Table Events
| Event Name | Description | Parameters |
@ -1480,7 +1473,7 @@ When the row content is too long and you do not want to display the horizontal s
| expand | triggers when user expands or collapses a row | row, expanded |
### Table Methods
| Method | Description | Parameter |
| Method | Description | Parameters |
|------|--------|-------|
| clearSelection | clear selection, might be useful when `reserve-selection` is on | selection |
| toggleRowSelection | toggle if a certain row is selected. With the second parameter, you can directly set if this row is selected | row, selected |
@ -1501,8 +1494,6 @@ When the row content is too long and you do not want to display the horizontal s
| resizable | whether column width can be resized, works when `border` of `el-table` is `true` | boolean | — | false |
| formatter | function that formats content | Function(row, column) | — | — |
| show-overflow-tooltip | whether to hide extra content and show them in a tooltip when hovering on the cell | boolean | — | false |
| context | context of Table-column, e.g. `_self` refers to the current context, `$parent` parent context, `$root` root context | Object | - | current context where Table lies |
| inline-template | by using this attribute, you can customize column template. Row data can be accessed by `row` object. In your template, you have access to the following: `{ row (current row), column (current column), $index (row index), store (table store) }` | — | — |
| align | alignment | string | left/center/right | left |
| header-align | alignment of the table header. If omitted, the value of the above `align` attribute will be applied | String | left/center/right | — |
| class-name | class name of cells in the column | string | — | — |

View File

@ -162,6 +162,7 @@ Can pick an arbitrary time range.
| end | end time | string | — | 18:00 |
| step | time step | string | — | 00:30 |
| minTime | minimum time, any time before this time will be disabled | string | — | 00:00 |
| maxTime | maximum time, any time after this time will be disabled | string | — | - |
### Time Picker Options
| Attribute | Description | Type | Accepted Values | Default |

View File

@ -1,5 +1,5 @@
<script>
import { addClass } from 'wind-dom/src/class';
import { addClass } from 'element-ui/src/utils/dom';
export default {
data() {
return {

View File

@ -0,0 +1,238 @@
<script>
export default {
mounted() {
this.$nextTick(() => {
const demos = document.querySelectorAll('.source');
demos[0].style.padding = '0';
demos[0].className += ' small';
demos[3].className += ' medium';
});
}
}
</script>
<style>
.demo-carousel .block {
padding: 30px;
text-align: center;
border-right: solid 1px #EFF2F6;
float: left;
width: 50%;
box-sizing: border-box;
&:last-child {
border-right: none;
}
}
.demo-carousel .demonstration {
display: block;
color: #8492a6;
font-size: 14px;
margin-bottom: 20px;
}
.demo-carousel .el-carousel__container {
text-align: center;
}
.demo-carousel .el-carousel__item {
h3 {
color: #fff;
font-size: 18px;
line-height: 300px;
margin: 0;
}
&:nth-child(2n) {
background-color: #99a9bf;
}
&:nth-child(2n+1) {
background-color: #d3dce6;
}
}
.demo-carousel .small h3 {
font-size: 14px;
line-height: 150px;
}
.demo-carousel .medium h3 {
font-size: 14px;
line-height: 200px;
}
</style>
## Carousel 走马灯
在有限空间内,循环播放同一类型的图片、文字等内容
### 基础用法
适用广泛的基础用法
::: demo 结合使用`el-carousel`和`el-carousel-item`标签就得到了一个走马灯。幻灯片的内容是任意的,需要放在`el-carousel-item`标签中。默认情况下,在鼠标 hover 底部的指示器时就会触发切换。通过设置`trigger`属性为`click`,可以达到点击触发的效果。
```html
<template>
<div class="block">
<span class="demonstration">默认 Hover 指示器触发</span>
<el-carousel height="150px">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</div>
<div class="block">
<span class="demonstration">Click 指示器触发</span>
<el-carousel trigger="click" height="150px">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</div>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 150px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### 指示器
可以将指示器的显示位置设置在容器外部
::: demo `indicator-position`属性定义了指示器的位置。默认情况下,它会显示在走马灯内部,设置为`outside`则会显示在外部;设置为`none`则不会显示指示器。
```html
<template>
<el-carousel indicator-position="outside">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### 切换箭头
可以设置切换箭头的显示时机
::: demo `arrow`属性定义了切换箭头的显示时机。默认情况下,切换箭头只有在鼠标 hover 到走马灯上时才会显示;若将`arrow`设置为`always`,则会一直显示;设置为`never`,则会一直隐藏。
```html
<template>
<el-carousel :interval="5000" arrow="always">
<el-carousel-item v-for="item in 4">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### 卡片化
当页面宽度方向空间空余,但高度方向空间匮乏时,可使用卡片风格
::: demo 将`type`属性设置为`card`即可启用卡片模式。从交互上来说,卡片模式和一般模式的最大区别在于,可以通过直接点击两侧的幻灯片进行切换。
```html
<template>
<el-carousel :interval="4000" type="card" height="200px">
<el-carousel-item v-for="item in 6">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</template>
<style>
.el-carousel__item h3 {
color: #475669;
font-size: 14px;
opacity: 0.75;
line-height: 200px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
</style>
```
:::
### Carousel Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| height | 走马灯的高度 | number | — | 300 |
| initial-index | 初始状态激活的幻灯片的索引,从 0 开始 | number | — | 0 |
| trigger | 指示器的触发方式 | string | click | — |
| autoplay | 是否自动切换 | boolean | — | true |
| interval | 自动切换的时间间隔,单位为毫秒 | number | — | 3000 |
| indicator-position | 指示器的位置 | string | outside/none | — |
| arrow | 切换箭头的显示时机 | string | always/hover/never | hover |
| type | 走马灯的类型 | string | card | — |
### Carousel Events
| 事件名称 | 说明 | 回调参数 |
|---------|---------|---------|
| change | 幻灯片切换时触发 | 目前激活的幻灯片的索引,原幻灯片的索引 |
### Carousel Methods
| 方法名 | 说明 | 参数 |
|---------- |-------------- | - |
| setActiveItem | 手动切换幻灯片 | 需要切换的幻灯片的索引,从 0 开始;或相应 `el-carousel-item``name` 属性值 |
| prev | 切换至上一张幻灯片 | — |
| next | 切换至下一张幻灯片 | — |
### Carousel-Item Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| name | 幻灯片的名字,可用作 `setActiveItem` 的参数 | string | — | — |

View File

@ -55,7 +55,7 @@
```
:::
## 禁用状态
### 禁用状态
多选框不可用状态。

View File

@ -0,0 +1,150 @@
<script>
export default {
data() {
return {
activeNames: ['1'],
activeName: '1'
};
},
methods: {
handleChange(val) {
console.log(val);
}
}
}
</script>
<style>
.demo-collapse {
.el-collapse-item__header {
.header-icon {
margin-left: 5px;
}
}
}
</style>
## Collapse 折叠面板
通过折叠面板收纳内容区域
### 基础用法
可同时展开多个面板,面板之间不影响
:::demo
```html
<el-collapse v-model="activeNames" @change="handleChange">
<el-collapse-item title="一致性 Consistency" name="1">
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
</el-collapse-item>
<el-collapse-item title="反馈 Feedback" name="2">
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
</el-collapse-item>
<el-collapse-item title="效率 Efficiency" name="3">
<div>简化流程:设计简洁直观的操作流程;</div>
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
</el-collapse-item>
<el-collapse-item title="可控 Controllability" name="4">
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
</el-collapse-item>
</el-collapse>
<script>
export default {
data() {
return {
activeNames: ['1']
};
}
}
</script>
```
:::
### 手风琴效果
每次只能展开一个面板
:::demo 通过 `accordion` 属性来设置是否以手风琴模式显示。
```html
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="一致性 Consistency" name="1">
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
</el-collapse-item>
<el-collapse-item title="反馈 Feedback" name="2">
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
</el-collapse-item>
<el-collapse-item title="效率 Efficiency" name="3">
<div>简化流程:设计简洁直观的操作流程;</div>
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
</el-collapse-item>
<el-collapse-item title="可控 Controllability" name="4">
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
</el-collapse-item>
</el-collapse>
<script>
export default {
data() {
return {
activeName: '1'
};
}
}
</script>
```
:::
### 自定义面板标题
除了可以通过 `title` 属性以外,还可以通过作用域插槽来实现自定义面板的标题内容,以实现增加图标等效果。
:::demo
```html
<el-collapse accordion>
<el-collapse-item title="一致性 Consistency">
<template slot="title" scope="props">
{{props.title}}<i class="header-icon el-icon-information"></i>
</template>
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
</el-collapse-item>
<el-collapse-item title="反馈 Feedback">
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
</el-collapse-item>
<el-collapse-item title="效率 Efficiency">
<div>简化流程:设计简洁直观的操作流程;</div>
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
</el-collapse-item>
<el-collapse-item title="可控 Controllability">
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
</el-collapse-item>
</el-collapse>
```
:::
### Collapse Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| accordion | 是否手风琴模式 | boolean | — | false |
| value | 当前激活的面板(如果是手风琴模式,绑定值类型需要为`string`,否则为`array`) | string/array | — | — |
### Collapse Events
| 事件名称 | 说明 | 回调参数 |
|---------|---------|---------|
| change | 当前激活面板改变时触发(如果是手风琴模式,参数 `activeNames` 类型为`string`,否则为`array`) | (activeNames: array\|string) |
### Collapse Item Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
| name | 唯一标志符 | string/number | — | — |
| title | 面板标题 | string | — | — |

View File

@ -303,6 +303,7 @@
|---------- |-------------- |---------- |-------------------------------- |-------- |
| shortcuts | 设置快捷选项,需要传入 { text, onClick } 对象用法参考 demo 或下表 | Object[] | - | - |
| disabledDate | 设置禁用状态,参数为当前日期,要求返回 Boolean | Function | - | - |
| firstDayOfWeek | 周起始日 | Number | 1 到 7 | 7 |
### Shortcuts
| 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -117,7 +117,7 @@
```
:::
<script>
import { addClass } from 'wind-dom/src/class';
import { addClass } from 'element-ui/src/utils/dom';
export default {
methods: {
handleSizeChange(val) {

View File

@ -45,7 +45,7 @@
},
"dependencies": {
"element-ui": "^1.0.0",
"vue": "^2.0.5"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-core": "^6.0.0",

View File

@ -587,15 +587,13 @@
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="操作"
width="100">
<span>
<template scope="scope">
<el-button @click="handleClick" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -797,19 +795,17 @@
width="120">
</el-table-column>
<el-table-column
inline-template
:context="_self"
fixed="right"
label="操作"
width="120">
<span>
<template scope="scope">
<el-button
@click.native.prevent="deleteRow($index, tableData4)"
@click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text"
size="small">
移除
</el-button>
</span>
</template>
</el-table-column>
</el-table>
</template>
@ -1061,7 +1057,7 @@
选择多行数据时使用 Checkbox。
:::demo 实现多选非常简单: 手动添加一个`el-table-column`,设`type`属性为`selection`即可。在本例中,为了方便说明其他属性,我们还使用了`inline-template`和`show-overflow-tooltip`:设置了`inline-template`属性后,可以通过调用`row`对象中的值取代`prop`属性的设置;默认情况下若内容过多会折行显示,若需要单行显示可以使用`show-overflow-tooltip`属性,它接受一个`Boolean`,为`true`时多余的内容会在 hover 时以 tooltip 的形式显示出来。
:::demo 实现多选非常简单: 手动添加一个`el-table-column`,设`type`属性为`selection`即可;默认情况下若内容过多会折行显示,若需要单行显示可以使用`show-overflow-tooltip`属性,它接受一个`Boolean`,为`true`时多余的内容会在 hover 时以 tooltip 的形式显示出来。
```html
<template>
<el-table
@ -1074,10 +1070,9 @@
width="55">
</el-table-column>
<el-table-column
inline-template
label="日期"
width="120">
<div>{{ row.date }}</div>
<template scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
prop="name"
@ -1234,9 +1229,12 @@
label="标签"
width="100"
:filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
:filter-method="filterTag"
inline-template>
<el-tag :type="row.tag === '家' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag>
:filter-method="filterTag">
<template scope="scope">
<el-tag
:type="scope.row.tag === '家' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
@ -1284,7 +1282,7 @@
### 自定义列模板
自定义列的显示内容,可组合其他组件使用。
:::demo 通过设置 `inline-template` 属性可以开启自定义模板功能,此时 `el-table-column` 的上下文指的是 `el-table` 所处的上下文,当然你可以通过 `context` 属性指定上下文环境,例如设置成 `:context="_self"` 就是指的当前上下文。有些时候我们会把 table 封装在其他组件里,通过 slot 设置 `table-column`,这样的话就要注意设置 `context`。在 column 组件内部,可以获取到 row, column, $index 和 storetable 内部的状态管理)的数据。
:::demo 通过 `Scoped slot` 可以获取到 row, column, $index 和 storetable 内部的状态管理)的数据,用法参考 demo。(`1.1` 后支持通过 [Scoped slot](https://vuejs.org/v2/guide/components.html#Scoped-Slots) 自定义模板。之前的 `inline-template` 同样适用,但不推荐。)
```html
<template>
<el-table
@ -1292,43 +1290,36 @@
border
style="width: 100%">
<el-table-column
inline-template
label="日期"
width="180">
<div>
<template scope="scope">
<el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span>
</div>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column
inline-template
label="姓名"
width="180">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ row.name }}</p>
<p>住址: {{ row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag>
</div>
</el-popover>
<template scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag>{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
:context="_self"
inline-template
label="操作">
<div>
<el-table-column label="操作">
<template scope="scope">
<el-button
size="small"
@click="handleEdit($index, row)">
编辑
</el-button>
@click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete($index, row)">
删除
</el-button>
</div>
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
@ -1454,6 +1445,8 @@
| empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | - | 暂无数据 |
| default-expand-all | 是否默认展开所有行,当 Table 中存在 type="expand" 的 Column 的时候有效 | Boolean | - | false |
| expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。| Array | - | |
| virtual-scrollbar | 启用虚拟滚动条 | Boolean | - | false |
### Table Events
| 事件名 | 说明 | 参数 |
@ -1495,8 +1488,6 @@
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | Function(row, column) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | Boolean | — | false |
| context | 设置上下文环境,例如设置当前上下文就是 `_self`,父级就是 `$parent`,根组件 `$root` | Object | - | Table 所处上下文 |
| inline-template | 指定该属性后可以自定义 column 模板,参考多选的时间列,通过 row 获取行信息。总共可以获取到 `{ row(当前行), column(当前列), $index(行数), store(table store) }` 以及 Table 所处的上下文环境。 | — | — |
| align | 对齐方式 | String | left/center/right | left |
| header-align | 表头对齐方式,若不设置该项,则使用表格的对齐方式 | String | left/center/right | — |
| class-name | 列的 className | string | — | — |

View File

@ -169,6 +169,7 @@
| end | 结束时间 | string | — | 18:00 |
| step | 间隔时间 | string | — | 00:30 |
| minTime | 最小时间,小于该时间的时间段将被禁用 | string | — | 00:00 |
| maxTime | 最大时间,大于该时间的时间段将被禁用 | string | — | - |
### Time Picker Options
| 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -8,7 +8,7 @@
</head>
<body>
<div id="app"></div><% if (process.env.NODE_ENV === 'production') { %>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.runtime.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.runtime.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.min.js"></script><% } %>
</body>
<% if (process.env.NODE_ENV === 'production') { %><script>
@ -19,5 +19,10 @@
ga('create', 'UA-84335471-1', 'auto');
ga('send', 'pageview');
window.addEventListener('hashchange', function () {
ga('set', 'page', window.location.href);
ga('send', 'pageview');
});
</script><% } %>
</html>

View File

@ -207,6 +207,14 @@
{
"path": "/card",
"title": "Card 卡片"
},
{
"path": "/carousel",
"title": "Carousel 走马灯"
},
{
"path": "/collapse",
"title": "Collapse 折叠面板"
}
]
}
@ -421,6 +429,14 @@
{
"path": "/card",
"title": "Card"
},
{
"path": "/carousel",
"title": "Carousel"
},
{
"path": "/collapse",
"title": "Collapse"
}
]
}

View File

@ -41,16 +41,16 @@
"bugs": {
"url": "https://github.com/ElemeFE/element/issues"
},
"unpkg": "lib/index.js",
"style": "lib/theme-default/index.css",
"dependencies": {
"async-validator": "^1.6.6",
"babel-helper-vue-jsx-merge-props": "^2.0.0",
"deepmerge": "^1.2.0",
"throttle-debounce": "^1.0.1",
"vue-popup": "^0.2.14",
"wind-dom": "0.0.3"
"throttle-debounce": "^1.0.1"
},
"peerDependencies": {
"vue": "^2.0.0"
"vue": "^2.1.6"
},
"devDependencies": {
"babel-cli": "^6.14.0",
@ -64,7 +64,7 @@
"cheerio": "^0.18.0",
"cooking": "^1.2.0",
"cooking-lint": "^0.1.3",
"cooking-vue2": "^0.1.4",
"cooking-vue2": "^0.3.0",
"copy-webpack-plugin": "^4.0.1",
"coveralls": "^2.11.14",
"cp-cli": "^1.0.2",
@ -112,11 +112,11 @@
"transliteration": "^1.1.11",
"uppercamelcase": "^1.1.0",
"url-loader": "^0.5.7",
"vue": "2.0.5",
"vue-loader": "^9.9.0",
"vue": "2.1.6",
"vue-loader": "^10.0.2",
"vue-markdown-loader": "^0.5.1",
"vue-router": "^2.0.0",
"vue-template-compiler": "2.0.5",
"vue-template-compiler": "2.1.6",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.15.1",
"webpack-node-externals": "^1.5.4"

View File

@ -0,0 +1,8 @@
import ElCarouselItem from '../carousel/src/item';
/* istanbul ignore next */
ElCarouselItem.install = function(Vue) {
Vue.component(ElCarouselItem.name, ElCarouselItem);
};
export default ElCarouselItem;

View File

@ -0,0 +1,10 @@
import ElCarousel from './src/main';
import ElCarouselItem from './src/item';
/* istanbul ignore next */
export default function(Vue) {
Vue.component(ElCarousel.name, ElCarousel);
Vue.component(ElCarouselItem.name, ElCarouselItem);
};
export { ElCarousel, ElCarouselItem };

View File

@ -0,0 +1,18 @@
var cooking = require('cooking');
var path = require('path');
var config = require('../../build/config');
cooking.set({
entry: {
index: path.join(__dirname, '_index.js')
},
dist: path.join(__dirname, 'lib'),
template: false,
format: 'umd',
moduleName: 'ElCarousel',
extends: ['vue2'],
alias: config.alias,
externals: { vue: config.vue }
});
module.exports = cooking.resolve();

View File

@ -0,0 +1,8 @@
import Carousel from './src/main';
/* istanbul ignore next */
Carousel.install = function(Vue) {
Vue.component(Carousel.name, Carousel);
};
export default Carousel;

View File

@ -0,0 +1,17 @@
{
"name": "element-carousel",
"version": "0.0.0",
"description": "A carousel component for Vue.js.",
"main": "lib/index.js",
"keywords": [
"element",
"vue",
"component"
],
"repository": "https://github.com/ElemeFE/element/tree/master/packages/carousel",
"author": "elemefe",
"license": "MIT",
"dependencies": {
"throttle-debounce": "^1.0.1"
}
}

View File

@ -0,0 +1,106 @@
<template>
<div
v-show="ready"
class="el-carousel__item"
:class="{
'is-active': active,
'el-carousel__item--card': $parent.type === 'card',
'is-in-stage': inStage,
'is-hover': hover
}"
@click="handleItemClick"
:style="{
msTransform: `translateX(${ translate }px) scale(${ scale })`,
webkitTransform: `translateX(${ translate }px) scale(${ scale })`,
transform: `translateX(${ translate }px) scale(${ scale })`
}">
<div
v-if="$parent.type === 'card'"
v-show="!active"
class="el-carousel__mask">
</div>
<slot></slot>
</div>
</template>
<script>
const CARD_SCALE = 0.83;
export default {
name: 'ElCarouselItem',
props: {
name: String
},
data() {
return {
hover: false,
translate: 0,
scale: 1,
active: false,
ready: false,
inStage: false
};
},
methods: {
processIndex(index, activeIndex, length) {
if (activeIndex === 0 && index === length - 1) {
return -1;
} else if (activeIndex === length - 1 && index === 0) {
return length;
} else if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
return length + 1;
} else if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
return -2;
}
return index;
},
calculateTranslate(index, activeIndex, parentWidth) {
if (this.inStage) {
return parentWidth * ((2 - CARD_SCALE) * (index - activeIndex) + 1) / 4;
} else if (index < activeIndex) {
return -(1 + CARD_SCALE) * parentWidth / 4;
} else {
return (3 + CARD_SCALE) * parentWidth / 4;
}
},
translateItem(index, activeIndex) {
const parentWidth = this.$parent.$el.offsetWidth;
const length = this.$parent.items.length;
if (this.$parent.type === 'card') {
if (index !== activeIndex && length > 2) {
index = this.processIndex(index, activeIndex, length);
}
this.inStage = Math.round(Math.abs(index - activeIndex)) <= 1;
this.active = index === activeIndex;
this.translate = this.calculateTranslate(index, activeIndex, parentWidth);
this.scale = this.active ? 1 : CARD_SCALE;
} else {
this.active = index === activeIndex;
this.translate = parentWidth * (index - activeIndex);
}
this.ready = true;
},
handleItemClick() {
const parent = this.$parent;
if (parent && parent.type === 'card') {
const index = parent.items.indexOf(this);
parent.setActiveItem(index);
}
}
},
created() {
this.$parent && this.$parent.handleItemChange();
},
destroyed() {
this.$parent && this.$parent.handleItemChange();
}
};
</script>

View File

@ -0,0 +1,241 @@
<template>
<div
class="el-carousel"
:class="{ 'el-carousel--card': type === 'card' }"
@mouseenter.stop="handleMouseEnter"
@mouseleave.stop="handleMouseLeave">
<div
class="el-carousel__container"
:style="{ height: height }">
<transition name="carousel-arrow-left">
<button
v-if="arrow !== 'never'"
v-show="arrow === 'always' || hover"
@mouseenter="handleButtonEnter('left')"
@mouseleave="handleButtonLeave"
@click.stop="throttledArrowClick(activeIndex - 1)"
class="el-carousel__arrow el-carousel__arrow--left">
<i class="el-icon-arrow-left"></i>
</button>
</transition>
<transition name="carousel-arrow-right">
<button
v-if="arrow !== 'never'"
v-show="arrow === 'always' || hover"
@mouseenter="handleButtonEnter('right')"
@mouseleave="handleButtonLeave"
@click.stop="throttledArrowClick(activeIndex + 1)"
class="el-carousel__arrow el-carousel__arrow--right">
<i class="el-icon-arrow-right"></i>
</button>
</transition>
<slot></slot>
</div>
<ul
class="el-carousel__indicators"
v-if="indicatorPosition !== 'none'"
:class="{ 'el-carousel__indicators--outside': indicatorPosition === 'outside' || type === 'card' }">
<li
v-for="(item, index) in items"
class="el-carousel__indicator"
:class="{ 'is-active': index === activeIndex }"
@mouseenter="throttledIndicatorHover(index)"
@click.stop="handleIndicatorClick(index)">
<button class="el-carousel__button"></button>
</li>
</ul>
</div>
</template>
<script>
import throttle from 'throttle-debounce/throttle';
import debounce from 'throttle-debounce/debounce';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
export default {
name: 'ElCarousel',
props: {
initialIndex: {
type: Number,
default: 0
},
height: String,
trigger: {
type: String,
default: 'hover'
},
autoPlay: {
type: Boolean,
default: true
},
interval: {
type: Number,
default: 3000
},
indicatorPosition: String,
indicator: {
type: Boolean,
default: true
},
arrow: {
type: String,
default: 'hover'
},
type: String
},
data() {
return {
items: [],
activeIndex: -1,
containerWidth: 0,
timer: null,
hover: false
};
},
watch: {
activeIndex(val, oldVal) {
this.resetItemPosition();
this.$emit('change', val, oldVal);
}
},
methods: {
handleMouseEnter() {
this.hover = true;
this.pauseTimer();
},
handleMouseLeave() {
this.hover = false;
this.startTimer();
},
itemInStage(item, index) {
const length = this.items.length;
if (index === length - 1 && item.inStage && this.items[0].active ||
(item.inStage && this.items[index + 1] && this.items[index + 1].active)) {
return 'left';
} else if (index === 0 && item.inStage && this.items[length - 1].active ||
(item.inStage && this.items[index - 1] && this.items[index - 1].active)) {
return 'right';
}
return false;
},
handleButtonEnter(arrow) {
this.items.forEach((item, index) => {
if (arrow === this.itemInStage(item, index)) {
item.hover = true;
}
});
},
handleButtonLeave() {
this.items.forEach(item => {
item.hover = false;
});
},
handleItemChange() {
debounce(100, () => {
this.updateItems();
});
},
updateItems() {
this.items = this.$children.filter(child => child.$options.name === 'ElCarouselItem');
},
resetItemPosition() {
this.items.forEach((item, index) => {
item.translateItem(index, this.activeIndex);
});
},
playSlides() {
if (this.activeIndex < this.items.length - 1) {
this.activeIndex++;
} else {
this.activeIndex = 0;
}
},
pauseTimer() {
clearInterval(this.timer);
},
startTimer() {
if (this.interval <= 0 || !this.autoPlay) return;
this.timer = setInterval(this.playSlides, this.interval);
},
setActiveItem(index) {
if (typeof index === 'string') {
const filteredItems = this.items.filter(item => item.name === index);
if (filteredItems.length > 0) {
index = this.items.indexOf(filteredItems[0]);
}
}
index = Number(index);
if (isNaN(index) || index !== Math.floor(index)) {
process.env.NODE_ENV !== 'production' &&
console.warn('[Element Warn][Carousel]index must be an integer.');
return;
}
let length = this.items.length;
if (index < 0) {
this.activeIndex = length - 1;
} else if (index >= length) {
this.activeIndex = 0;
} else {
this.activeIndex = index;
}
},
prev() {
this.setActiveItem(this.activeIndex - 1);
},
next() {
this.setActiveItem(this.activeIndex + 1);
},
handleIndicatorClick(index) {
this.activeIndex = index;
},
handleIndicatorHover(index) {
if (this.trigger === 'hover' && index !== this.activeIndex) {
this.activeIndex = index;
}
}
},
created() {
this.throttledArrowClick = throttle(300, true, index => {
this.setActiveItem(index);
});
this.throttledIndicatorHover = throttle(300, index => {
this.handleIndicatorHover(index);
});
},
mounted() {
this.updateItems();
this.$nextTick(() => {
addResizeListener(this.$el, this.resetItemPosition);
if (this.initialIndex < this.items.length && this.initialIndex >= 0) {
this.activeIndex = this.initialIndex;
}
this.startTimer();
});
},
beforeDestroy() {
if (this.$el) removeResizeListener(this.$el, this.resetItemPosition);
}
};
</script>

View File

@ -0,0 +1,8 @@
import ElCollapseItem from '../collapse/src/collapse-item.vue';
/* istanbul ignore next */
ElCollapseItem.install = function(Vue) {
Vue.component(ElCollapseItem.name, ElCollapseItem);
};
export default ElCollapseItem;

View File

@ -0,0 +1,13 @@
import ElCollapse from './src/collapse';
import ElCollapseItem from './src/collapse-item.vue';
/* istanbul ignore next */
export default function install(Vue) {
Vue.component(ElCollapseItem.name, ElCollapseItem);
Vue.component(ElCollapse.name, ElCollapse);
};
export {
ElCollapse,
ElCollapseItem
};

View File

@ -0,0 +1,18 @@
var cooking = require('cooking');
var path = require('path');
var config = require('../../build/config');
cooking.set({
entry: {
index: path.join(__dirname, '_index.js')
},
dist: path.join(__dirname, 'lib'),
template: false,
format: 'umd',
moduleName: 'ElCollapse',
extends: ['vue2'],
alias: config.alias,
externals: { vue: config.vue }
});
module.exports = cooking.resolve();

View File

@ -0,0 +1,9 @@
import ElCollapse from './src/collapse';
/* istanbul ignore next */
ElCollapse.install = function(Vue) {
Vue.component(ElCollapse.name, ElCollapse);
};
export default ElCollapse;

View File

@ -0,0 +1,15 @@
{
"name": "element-collapse",
"version": "1.0.0",
"description": "A row component for Vue.",
"keywords": [
"element",
"vue",
"component"
],
"main": "./lib/index.js",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/collapse",
"author": "haiping.zeng@ele.me",
"license": "MIT",
"dependencies": {}
}

View File

@ -0,0 +1,115 @@
<template>
<div class="el-collapse-item" :class="{'is-active': isActive}">
<div class="el-collapse-item__header" @click="handleHeaderClick">
<i class="el-collapse-item__header__arrow el-icon-arrow-right"></i>
<slot name="title" :title="title">{{title}}</slot>
</div>
<div class="el-collapse-item__wrap" ref="content" :style="contentStyle">
<div class="el-collapse-item__content">
<slot></slot>
</div>
</div>
</div>
</template>
<script>
import { once } from 'element-ui/src/utils/dom';
import Emitter from 'element-ui/src/mixins/emitter';
function getTransitionendEvent(el) {
let t;
let transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
};
export default {
name: 'ElCollapseItem',
componentName: 'ElCollapseItem',
mixins: [Emitter],
data() {
return {
contentStyle: {},
contentHeight: 0
};
},
props: {
title: String,
name: {
type: [String, Number],
default() {
return this._uid;
}
}
},
computed: {
isActive() {
return this.$parent.activeNames.indexOf(this.name) > -1;
}
},
watch: {
'isActive'(value) {
value ? this.open() : this.close();
}
},
methods: {
open() {
const contentElm = this.$refs.content;
const contentStyle = this.contentStyle;
contentStyle.display = 'block';
this.$nextTick(_ => {
contentStyle.height = this.contentHeight + 'px';
once(contentElm, getTransitionendEvent(contentElm), () => {
contentStyle.height = 'auto';
});
});
},
close() {
const contentElm = this.$refs.content;
const contentHeight = contentElm.clientHeight;
const contentStyle = this.contentStyle;
this.contentHeight = contentHeight;
this.$set(this.contentStyle, 'height', contentHeight + 'px');
this.$nextTick(_ => {
contentStyle.height = '0';
once(contentElm, getTransitionendEvent(contentElm), () => {
this.$set(this.contentStyle, 'display', 'none');
});
});
},
init() {
this.contentHeight = this.$refs.content.clientHeight;
if (!this.isActive) {
this.$set(this.contentStyle, 'height', '0');
this.$set(this.contentStyle, 'display', 'none');
}
},
handleHeaderClick() {
this.dispatch('ElCollapse', 'item-click', this);
}
},
mounted() {
this.init();
}
};
</script>

View File

@ -0,0 +1,62 @@
<template>
<div class="el-collapse">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ElCollapse',
componentName: 'ElCollapse',
props: {
accordion: Boolean,
value: {
type: [Array, String],
default() {
return [];
}
}
},
data() {
return {
activeNames: [].concat(this.value)
};
},
watch: {
value(value) {
this.activeNames = [].concat(value);
}
},
methods: {
setActiveNames(activeNames) {
let value = this.accordion ? activeNames[0] : activeNames;
this.activeNames = [].concat(value);
this.$emit('input', value);
this.$emit('change', value);
},
handleItemClick(item) {
if (this.accordion) {
this.setActiveNames(this.activeNames[0] === item.name ? '' : item.name);
} else {
let activeNames = this.activeNames.slice(0);
let index = activeNames.indexOf(item.name);
if (index > -1) {
activeNames.splice(index, 1);
} else {
activeNames.push(item.name);
}
this.setActiveNames(activeNames);
}
}
},
created() {
this.$on('item-click', this.handleItemClick);
}
};
</script>

View File

@ -12,6 +12,5 @@
"author": "long.zhang@ele.me",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -9,13 +9,7 @@
<tbody>
<tr>
<th v-if="showWeekNumber">{{ t('el.datepicker.week') }}</th>
<th>{{ t('el.datepicker.weeks.sun') }}</th>
<th>{{ t('el.datepicker.weeks.mon') }}</th>
<th>{{ t('el.datepicker.weeks.tue') }}</th>
<th>{{ t('el.datepicker.weeks.wed') }}</th>
<th>{{ t('el.datepicker.weeks.thu') }}</th>
<th>{{ t('el.datepicker.weeks.fri') }}</th>
<th>{{ t('el.datepicker.weeks.sat') }}</th>
<th v-for="week in WEEKS">{{ t('el.datepicker.weeks.' + week) }}</th>
</tr>
<tr
class="el-date-table__row"
@ -32,9 +26,10 @@
<script>
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION } from '../util';
import { hasClass } from 'wind-dom/src/class';
import { hasClass } from 'element-ui/src/utils/dom';
import Locale from 'element-ui/src/mixins/locale';
const WEEKS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
const clearHours = function(time) {
const cloneDate = new Date(time);
cloneDate.setHours(0, 0, 0, 0);
@ -45,6 +40,12 @@
mixins: [Locale],
props: {
firstDayOfWeek: {
default: 7,
type: Number,
validator: val => val >= 1 && val <= 7
},
date: {},
year: {},
@ -83,6 +84,17 @@
},
computed: {
offsetDay() {
const week = this.firstDayOfWeek;
// 3217654 -1
return week > 3 ? 7 - week : -week;
},
WEEKS() {
const week = this.firstDayOfWeek;
return WEEKS.concat(WEEKS).slice(week, week + 7);
},
monthDate() {
return this.date.getDate();
},
@ -99,6 +111,7 @@
day = (day === 0 ? 7 : day);
const offset = this.offsetDay;
const rows = this.tableRows;
let count = 1;
let firstDayPosition;
@ -125,7 +138,7 @@
cell.type = 'normal';
const index = i * 7 + j;
const time = startDate.getTime() + DAY_DURATION * index;
const time = startDate.getTime() + DAY_DURATION * (index - offset);
cell.inRange = time >= clearHours(this.minDate) && time <= clearHours(this.maxDate);
cell.start = this.minDate && time === clearHours(this.minDate);
cell.end = this.maxDate && time === clearHours(this.maxDate);
@ -135,14 +148,14 @@
cell.type = 'today';
}
if (i === 0) {
if (j >= day) {
if (i >= 0 && i <= 1) {
if (j + i * 7 >= (day + offset)) {
cell.text = count++;
if (count === 2) {
firstDayPosition = i * 7 + j;
}
} else {
cell.text = dateCountOfLastMonth - (day - j % 7) + 1;
cell.text = dateCountOfLastMonth - (day + offset - j % 7) + 1 + i * 7;
cell.type = 'prev-month';
}
} else {

View File

@ -49,7 +49,7 @@
<script type="text/babel">
import Locale from 'element-ui/src/mixins/locale';
import { hasClass } from 'wind-dom/src/class';
import { hasClass } from 'element-ui/src/utils/dom';
export default {
props: {

View File

@ -1,56 +1,65 @@
<template>
<div class="el-time-spinner" :class="{ 'has-seconds': showSeconds }">
<div
@mouseenter="emitSelectRange('hours')"
@mousewheel="handleScroll('hour')"
<el-scrollbar
@mouseenter.native="emitSelectRange('hours')"
@mousewheel.native="handleScroll('hour')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
noresize
tag="ul"
ref="hour">
<ul class="el-time-spinner__list">
<li
@click="handleClick('hours', { value: hour, disabled: disabled }, true)"
v-for="(disabled, hour) in hoursList"
track-by="hour"
class="el-time-spinner__item"
:class="{ 'active': hour === hours, 'disabled': disabled }"
v-text="hour"></li>
</ul>
</div>
<div
@mouseenter="emitSelectRange('minutes')"
@mousewheel="handleScroll('minute')"
<li
@click="handleClick('hours', { value: hour, disabled: disabled }, true)"
v-for="(disabled, hour) in hoursList"
track-by="hour"
class="el-time-spinner__item"
:class="{ 'active': hour === hours, 'disabled': disabled }"
v-text="hour"></li>
</el-scrollbar>
<el-scrollbar
@mouseenter.native="emitSelectRange('minutes')"
@mousewheel.native="handleScroll('minute')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
noresize
tag="ul"
ref="minute">
<ul class="el-time-spinner__list">
<li
@click="handleClick('minutes', key, true)"
v-for="(minute, key) in 60"
class="el-time-spinner__item"
:class="{ 'active': key === minutes }"
v-text="key"></li>
</ul>
</div>
<div
<li
@click="handleClick('minutes', key, true)"
v-for="(minute, key) in 60"
class="el-time-spinner__item"
:class="{ 'active': key === minutes }"
v-text="key"></li>
</el-scrollbar>
<el-scrollbar
v-show="showSeconds"
@mouseenter="emitSelectRange('seconds')"
@mousewheel="handleScroll('second')"
@mouseenter.native="emitSelectRange('seconds')"
@mousewheel.native="handleScroll('second')"
class="el-time-spinner__wrapper"
wrap-style="max-height: inherit;"
view-class="el-time-spinner__list"
noresize
tag="ul"
ref="second">
<ul class="el-time-spinner__list">
<li
@click="handleClick('seconds', key, true)"
v-for="(second, key) in 60"
class="el-time-spinner__item"
:class="{ 'active': key === seconds }"
v-text="key"></li>
</ul>
</div>
<li
@click="handleClick('seconds', key, true)"
v-for="(second, key) in 60"
class="el-time-spinner__item"
:class="{ 'active': key === seconds }"
v-text="key"></li>
</el-scrollbar>
</div>
</template>
<script type="text/babel">
import { getRangeHours } from '../util';
import ElScrollbar from 'element-ui/packages/scrollbar';
export default {
components: { ElScrollbar },
props: {
hours: {
type: Number,
@ -78,7 +87,7 @@
if (!(newVal >= 0 && newVal <= 23)) {
this.hoursPrivate = oldVal;
}
this.$refs.hour.scrollTop = Math.max(0, (this.hoursPrivate - 2.5) * 32 + 80);
this.hourEl.scrollTop = Math.max(0, (this.hoursPrivate - 2.5) * 32 + 80);
this.$emit('change', { hours: newVal });
},
@ -86,7 +95,7 @@
if (!(newVal >= 0 && newVal <= 59)) {
this.minutesPrivate = oldVal;
}
this.$refs.minute.scrollTop = Math.max(0, (this.minutesPrivate - 2.5) * 32 + 80);
this.minuteEl.scrollTop = Math.max(0, (this.minutesPrivate - 2.5) * 32 + 80);
this.$emit('change', { minutes: newVal });
},
@ -94,7 +103,7 @@
if (!(newVal >= 0 && newVal <= 59)) {
this.secondsPrivate = oldVal;
}
this.$refs.second.scrollTop = Math.max(0, (this.secondsPrivate - 2.5) * 32 + 80);
this.secondEl.scrollTop = Math.max(0, (this.secondsPrivate - 2.5) * 32 + 80);
this.$emit('change', { seconds: newVal });
}
},
@ -102,6 +111,18 @@
computed: {
hoursList() {
return getRangeHours(this.selectableRange);
},
hourEl() {
return this.$refs.hour.wrap;
},
minuteEl() {
return this.$refs.minute.wrap;
},
secondEl() {
return this.$refs.second.wrap;
}
},
@ -138,14 +159,14 @@
handleScroll(type) {
const ajust = {};
ajust[`${type}s`] = Math.min(Math.floor((this.$refs[type].scrollTop - 80) / 32 + 3), 59);
ajust[`${type}s`] = Math.min(Math.floor((this[`${type}Elm`].scrollTop - 80) / 32 + 3), 59);
this.$emit('change', ajust);
},
ajustScrollTop() {
this.$refs.hour.scrollTop = Math.max(0, (this.hours - 2.5) * 32 + 80);
this.$refs.minute.scrollTop = Math.max(0, (this.minutes - 2.5) * 32 + 80);
this.$refs.second.scrollTop = Math.max(0, (this.seconds - 2.5) * 32 + 80);
this.hourEl.scrollTop = Math.max(0, (this.hours - 2.5) * 32 + 80);
this.minuteEl.scrollTop = Math.max(0, (this.minutes - 2.5) * 32 + 80);
this.secondEl.scrollTop = Math.max(0, (this.seconds - 2.5) * 32 + 80);
}
}
};

View File

@ -44,7 +44,7 @@
</template>
<script type="text/babel">
import { hasClass } from 'wind-dom/src/class';
import { hasClass } from 'element-ui/src/utils/dom';
export default {
props: {

View File

@ -88,6 +88,7 @@
:value="value"
:week="week"
:selection-mode="selectionMode"
:first-day-of-week="firstDayOfWeek"
:disabled-date="disabledDate">
</date-table>
<year-table
@ -377,6 +378,7 @@
visible: false,
currentView: 'date',
disabledDate: '',
firstDayOfWeek: 7,
year: null,
month: null,
week: null,

View File

@ -3,20 +3,22 @@
<div
v-show="visible"
:style="{ width: width + 'px' }"
class="el-picker-panel time-select"
:class="popperClass">
<div class="el-picker-panel__content">
:class="popperClass"
class="el-picker-panel time-select">
<el-scrollbar noresize wrap-class="el-picker-panel__content">
<div class="time-select-item"
v-for="item in items"
:class="{ selected: value === item.value, disabled: item.disabled }"
:disabled="item.disabled"
@click="handleClick(item)">{{ item.value }}</div>
</div>
</el-scrollbar>
</div>
</transition>
</template>
<script type="text/babel">
import ElScrollbar from 'element-ui/packages/scrollbar';
const parseTime = function(time) {
const values = ('' || time).split(':');
if (values.length >= 2) {
@ -69,9 +71,14 @@
};
export default {
components: { ElScrollbar },
watch: {
minTime(val) {
if (this.value && val && compareTime(this.value, val) === -1) {
value(val) {
if (!val) return;
if (this.minTime && compareTime(val, this.minTime) < 0) {
this.$emit('pick');
} else if (this.maxTime && compareTime(val, this.maxTime) > 0) {
this.$emit('pick');
}
}
@ -98,6 +105,7 @@
value: '',
visible: false,
minTime: '',
maxTime: '',
width: 0
};
},
@ -115,7 +123,8 @@
while (compareTime(current, end) <= 0) {
result.push({
value: current,
disabled: compareTime(current, this.minTime || '-1:-1') <= 0
disabled: compareTime(current, this.minTime || '-1:-1') <= 0 ||
compareTime(current, this.maxTime || '100:100') > 0
});
current = nextTime(current, step);
}

View File

@ -395,6 +395,7 @@ export default {
},
showPicker() {
if (this.$isServer) return;
if (!this.picker) {
this.panel.defaultValue = this.internalValue;
this.picker = new Vue(this.panel).$mount(document.createElement('div'));

View File

@ -22,7 +22,7 @@
</template>
<script>
import Popup from 'vue-popup';
import Popup from 'element-ui/src/utils/popup';
export default {
name: 'el-dialog',

View File

@ -13,6 +13,5 @@
"license": "MIT",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/input-number",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -40,7 +40,7 @@
</template>
<script>
import ElInput from 'element-ui/packages/input';
import { once, on } from 'wind-dom/src/event';
import { once, on } from 'element-ui/src/utils/dom';
export default {
name: 'ElInputNumber',
@ -50,11 +50,8 @@
let interval = null;
let startTime;
const handler = () => {
vnode.context[binding.expression]();
};
const clear = function() {
const handler = () => vnode.context[binding.expression]();
const clear = () => {
if (new Date() - startTime < 100) {
handler();
}
@ -62,12 +59,10 @@
interval = null;
};
on(el, 'mousedown', function() {
on(el, 'mousedown', () => {
startTime = new Date();
once(document, 'mouseup', clear);
interval = setInterval(function() {
handler();
}, 100);
interval = setInterval(handler, 100);
});
}
}

View File

@ -137,10 +137,9 @@
this.$refs.input.select();
},
resizeTextarea() {
if (this.$isServer) return;
var { autosize, type } = this;
if (!autosize || type !== 'textarea') {
return;
}
if (!autosize || type !== 'textarea') return;
const minRows = autosize.minRows;
const maxRows = autosize.maxRows;

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -1,8 +1,9 @@
import Vue from 'vue';
import { addClass, removeClass } from 'wind-dom/src/class';
import { addClass, removeClass } from 'element-ui/src/utils/dom';
let Mask = Vue.extend(require('./loading.vue'));
exports.install = Vue => {
if (Vue.prototype.$isServer) return;
let toggleLoading = (el, binding) => {
if (binding.value) {
Vue.nextTick(() => {

View File

@ -61,6 +61,7 @@ const addStyle = (options, parent, instance) => {
};
const Loading = (options = {}) => {
if (Vue.prototype.$isServer) return;
options = merge({}, defaults, options);
if (typeof options.target === 'string') {
options.target = document.querySelector(options.target);

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -102,6 +102,7 @@ const showNextMsg = () => {
};
const MessageBox = function(options, callback) {
if (Vue.prototype.$isServer) return;
if (typeof options === 'string') {
options = {
message: options

View File

@ -24,11 +24,11 @@
</template>
<script type="text/babel">
import Popup from 'vue-popup';
import Popup from 'element-ui/src/utils/popup';
import Locale from 'element-ui/src/mixins/locale';
import ElInput from 'element-ui/packages/input';
import ElButton from 'element-ui/packages/button';
import { addClass, removeClass } from 'wind-dom/src/class';
import { addClass, removeClass } from 'element-ui/src/utils/dom';
import { t } from 'element-ui/src/locale';
let typeMap = {

View File

@ -1,5 +1,5 @@
import Vue from 'vue';
import { PopupManager } from 'vue-popup';
import { PopupManager } from 'element-ui/src/utils/popup';
let MessageConstructor = Vue.extend(require('./main.vue'));
let instance;
@ -7,6 +7,7 @@ let instances = [];
let seed = 1;
var Message = function(options) {
if (Vue.prototype.$isServer) return;
options = options || {};
if (typeof options === 'string') {
options = {

View File

@ -1,5 +1,5 @@
import Vue from 'vue';
import { PopupManager } from 'vue-popup';
import { PopupManager } from 'element-ui/src/utils/popup';
let NotificationConstructor = Vue.extend(require('./main.vue'));
let instance;
@ -7,6 +7,7 @@ let instances = [];
let seed = 1;
var Notification = function(options) {
if (Vue.prototype.$isServer) return;
options = options || {};
let userOnClose = options.onClose;
let id = 'notification_' + seed++;

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"devDependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -17,7 +17,7 @@
<script>
import Popper from 'element-ui/src/utils/vue-popper';
import { on, off } from 'wind-dom/src/event';
import { on, off } from 'element-ui/src/utils/dom';
export default {
name: 'el-popover',

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -24,7 +24,7 @@
</template>
<script type="text/babel">
import { hasClass } from 'wind-dom/src/class';
import { hasClass } from 'element-ui/src/utils/dom';
export default {
name: 'el-rate',

View File

@ -0,0 +1,8 @@
import Scrollbar from './src/main';
/* istanbul ignore next */
Scrollbar.install = function(Vue) {
Vue.component(Scrollbar.name, Scrollbar);
};
export default Scrollbar;

View File

@ -0,0 +1,87 @@
import { on, off } from 'element-ui/src/utils/dom';
import { renderThumbStyle, BAR_MAP } from './util';
export default {
name: 'Bar',
props: {
vertical: Boolean,
size: String,
move: Number
},
computed: {
bar() {
return BAR_MAP[this.vertical ? 'vertical' : 'horizontal'];
},
wrap() {
return this.$parent.wrap;
}
},
render(h) {
const { size, move, bar } = this;
return (
<div
class={ ['el-scrollbar__bar', 'is-' + bar.key] }
onMousedown={ this.clickTrackHandler } >
<div
ref="thumb"
class="el-scrollbar__thumb"
onMousedown={ this.clickThumbHandler }
style={ renderThumbStyle({ size, move, bar }) }>
</div>
</div>
);
},
methods: {
clickThumbHandler(e) {
this.startDrag(e);
this[this.bar.axis] = (e.currentTarget[this.bar.offset] - (e[this.bar.client] - e.currentTarget.getBoundingClientRect()[this.bar.direction]));
},
clickTrackHandler(e) {
const offset = Math.abs(e.target.getBoundingClientRect()[this.bar.direction] - e[this.bar.client]);
const thumbHalf = (this.$refs.thumb[this.bar.offset] / 2);
const thumbPositionPercentage = ((offset - thumbHalf) * 100 / this.$el[this.bar.offset]);
this.wrap[this.bar.scroll] = (thumbPositionPercentage * this.wrap[this.bar.scrollSize] / 100);
},
startDrag(e) {
e.stopImmediatePropagation();
this.cursorDown = true;
on(document, 'mousemove', this.mouseMoveDocumentHandler);
on(document, 'mouseup', this.mouseUpDocumentHandler);
document.onselectstart = () => false;
},
mouseMoveDocumentHandler(e) {
if (this.cursorDown === false) return;
const prevPage = this[this.bar.axis];
if (!prevPage) return;
const offset = ((this.$el.getBoundingClientRect()[this.bar.direction] - e[this.bar.client]) * -1);
const thumbClickPosition = (this.$refs.thumb[this.bar.offset] - prevPage);
const thumbPositionPercentage = ((offset - thumbClickPosition) * 100 / this.$el[this.bar.offset]);
this.wrap[this.bar.scroll] = (thumbPositionPercentage * this.wrap[this.bar.scrollSize] / 100);
},
mouseUpDocumentHandler(e) {
this.cursorDown = false;
this[this.bar.axis] = 0;
off(document, 'mousemove', this.mouseMoveDocumentHandler);
document.onselectstart = null;
}
},
destroyed() {
off(document, 'mouseup', this.mouseUpDocumentHandler);
}
};

View File

@ -0,0 +1,125 @@
// reference https://github.com/noeldelgado/gemini-scrollbar/blob/master/index.js
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
import * as util from './util';
import Bar from './bar';
export default {
name: 'ElScrollbar',
components: { Bar },
props: {
native: Boolean,
wrapStyle: {},
wrapClass: {},
viewClass: {},
viewStyle: {},
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
tag: {
type: String,
default: 'div'
}
},
data() {
return {
sizeWidth: '0',
sizeHeight: '0',
moveX: 0,
moveY: 0
};
},
computed: {
wrap() {
return this.$refs.wrap;
}
},
render(h) {
let gutter = scrollbarWidth();
let style = this.wrapStyle;
if (gutter) {
const gutterWith = `-${gutter}px`;
if (Array.isArray(this.wrapStyle)) {
style = util.toObject(this.wrapStyle);
style.marginRight = style.marginBottom = gutterWith;
} else if (typeof this.wrapStyle === 'string') {
style += `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;
}
}
const view = h(this.tag, {
class: ['el-scrollbar__view', this.viewClass],
style: this.viewStyle,
ref: 'resize'
}, this.$slots.default);
const wrap = (
<div
ref="wrap"
style={ style }
onScroll={ this.handleScroll }
class={ [this.wrapClass, 'el-scrollbar__wrap el-scrollbar__wrap--hidden-default'] }>
{ [view] }
</div>
);
let nodes;
if (!this.native) {
nodes = ([
wrap,
<Bar
move={ this.moveX }
size={ this.sizeWidth }></Bar>,
<Bar
vertical
move={ this.moveY }
size={ this.sizeHeight }></Bar>
]);
} else {
nodes = ([
<div
ref="wrap"
class={ [this.wrapClass, 'el-scrollbar__wrap'] }
style={ style }>
{ [view] }
</div>
]);
}
return h('div', { class: 'el-scrollbar' }, nodes);
},
methods: {
handleScroll() {
const wrap = this.wrap;
this.moveY = ((wrap.scrollTop * 100) / wrap.clientHeight);
this.moveX = ((wrap.scrollLeft * 100) / wrap.clientWidth);
},
update() {
let heightPercentage, widthPercentage;
const wrap = this.wrap;
heightPercentage = (wrap.clientHeight * 100 / wrap.scrollHeight);
widthPercentage = (wrap.clientWidth * 100 / wrap.scrollWidth);
this.sizeHeight = (heightPercentage < 100) ? (heightPercentage + '%') : '';
this.sizeWidth = (widthPercentage < 100) ? (widthPercentage + '%') : '';
}
},
mounted() {
if (this.native) return;
this.$nextTick(this.update);
!this.noresize && addResizeListener(this.$refs.resize, this.update);
},
destroyed() {
if (this.native) return;
!this.noresize && removeResizeListener(this.$refs.resize, this.update);
}
};

View File

@ -0,0 +1,38 @@
import Vue from 'vue';
export const BAR_MAP = {
vertical: {
offset: 'offsetHeight',
scroll: 'scrollTop',
scrollSize: 'scrollHeight',
size: 'height',
key: 'vertical',
axis: 'Y',
client: 'clientY',
direction: 'top'
},
horizontal: {
offset: 'offsetWidth',
scroll: 'scrollLeft',
scrollSize: 'scrollWidth',
size: 'width',
key: 'horizontal',
axis: 'X',
client: 'clientX',
direction: 'left'
}
};
export function renderThumbStyle({ move, size, bar }) {
const style = {};
const translate = `translate${bar.axis}(${ move }%)`;
style[bar.size] = size;
style.transform = translate;
style.msTransform = translate;
style.webkitTransform = translate;
return style;
};
export const toObject = Vue.util.toObject;

View File

@ -12,7 +12,6 @@
"license": "MIT",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/select",
"devDependencies": {
"throttle-debounce": "^1.0.1",
"wind-dom": "0.0.3"
"throttle-debounce": "^1.0.1"
}
}

View File

@ -65,8 +65,10 @@
<el-select-menu
ref="popper"
v-show="visible && emptyText !== false">
<ul
class="el-select-dropdown__list"
<el-scrollbar
tag="ul"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
:class="{ 'is-empty': !allowCreate && filteredOptionsCount === 0 }"
v-show="options.length > 0 && !loading">
<el-option
@ -75,7 +77,7 @@
v-if="showNewOption">
</el-option>
<slot></slot>
</ul>
</el-scrollbar>
<p class="el-select-dropdown__empty" v-if="emptyText && !allowCreate">{{ emptyText }}</p>
</el-select-menu>
</transition>
@ -89,9 +91,10 @@
import ElSelectMenu from './select-dropdown.vue';
import ElOption from './option.vue';
import ElTag from 'element-ui/packages/tag';
import ElScrollbar from 'element-ui/packages/scrollbar';
import debounce from 'throttle-debounce/debounce';
import Clickoutside from 'element-ui/src/utils/clickoutside';
import { addClass, removeClass, hasClass } from 'wind-dom/src/class';
import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
import { t } from 'element-ui/src/locale';
const sizeMap = {
@ -148,7 +151,8 @@
ElInput,
ElSelectMenu,
ElOption,
ElTag
ElTag,
ElScrollbar
},
directives: { Clickoutside },
@ -301,6 +305,7 @@
},
options(val) {
if (this.$isServer) return;
this.optionsAllDisabled = val.length === val.filter(item => item.disabled === true).length;
if (this.multiple) {
this.resetInputHeight();

View File

@ -12,6 +12,5 @@
"author": "elemefe",
"license": "MIT",
"dependencies": {
"wind-dom": "0.0.3"
}
}

View File

@ -37,7 +37,7 @@
<script type="text/babel">
import ElInputNumber from 'element-ui/packages/input-number';
import ElTooltip from 'element-ui/packages/tooltip';
import { getStyle } from 'wind-dom/src/style';
import { getStyle } from 'element-ui/src/utils/dom';
export default {
name: 'ElSlider',

View File

@ -1,6 +1,7 @@
import Vue from 'vue';
var dropdowns = [];
document.addEventListener('click', function(event) {
!Vue.prototype.$isServer && document.addEventListener('click', function(event) {
dropdowns.forEach(function(dropdown) {
var target = event.target;
if (!dropdown || !dropdown.$el) return;

View File

@ -163,7 +163,7 @@
mounted() {
this.popperElm = this.$el;
this.referenceElm = this.cell;
this.table.$refs.bodyWrapper.addEventListener('scroll', () => {
this.table.bodyWrapper.addEventListener('scroll', () => {
this.updatePopper();
});

View File

@ -40,7 +40,7 @@ export default {
this._l(this.data, (row, $index) =>
[<tr
style={ this.rowStyle ? this.getRowStyle(row, $index) : null }
key={ this.$parent.rowKey ? this.getKeyOfRow(row, $index) : $index }
key={ this.table.rowKey ? this.getKeyOfRow(row, $index) : $index }
on-dblclick={ ($event) => this.handleDoubleClick($event, row) }
on-click={ ($event) => this.handleClick($event, row) }
on-contextmenu={ ($event) => this.handleContextMenu($event, row) }
@ -54,7 +54,7 @@ export default {
on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) }
on-mouseleave={ this.handleCellMouseLeave }>
{
column.renderCell.call(this._renderProxy, h, { row, column, $index, store: this.store, _self: this.context || this.$parent.$vnode.context })
column.renderCell.call(this._renderProxy, h, { row, column, $index, store: this.store, _self: this.context || this.table.$vnode.context })
}
</td>
)
@ -113,6 +113,10 @@ export default {
},
computed: {
table() {
return this.$parent.$parent.columns ? this.$parent.$parent : this.$parent;
},
data() {
return this.store.states.data;
},
@ -142,7 +146,7 @@ export default {
methods: {
getKeyOfRow(row, index) {
const rowKey = this.$parent.rowKey;
const rowKey = this.table.rowKey;
if (rowKey) {
return getRowIdentity(row, rowKey);
}
@ -181,7 +185,7 @@ export default {
},
handleCellMouseEnter(event, row) {
const table = this.$parent;
const table = this.table;
const cell = getCell(event);
if (cell) {
@ -200,8 +204,8 @@ export default {
const cell = getCell(event);
if (!cell) return;
const oldHoverState = this.$parent.hoverState;
this.$parent.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
const oldHoverState = this.table.hoverState;
this.table.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
},
handleMouseEnter(index) {
@ -213,17 +217,17 @@ export default {
},
handleContextMenu(event, row) {
const table = this.$parent;
const table = this.table;
table.$emit('row-contextmenu', row, event);
},
handleDoubleClick(event, row) {
const table = this.$parent;
const table = this.table;
table.$emit('row-dblclick', row, event);
},
handleClick(event, row) {
const table = this.$parent;
const table = this.table;
const cell = getCell(event);
let column;
if (cell) {

View File

@ -150,10 +150,6 @@ export default {
}
},
render() {
return (<div>{ this._t('default') }</div>);
},
data() {
return {
isSubColumn: false,
@ -184,9 +180,7 @@ export default {
created() {
this.customRender = this.$options.render;
this.$options.render = (h) => {
return (<div>{ this._t('default') }</div>);
};
this.$options.render = h => h('div', this.$slots.default);
let columnId = this.columnId = this.columnKey || ((this.$parent.tableId || (this.$parent.columnId + '_')) + 'column_' + columnIdSeed++);
@ -282,7 +276,6 @@ export default {
if (Object.prototype.toString.call(data._self) === '[object Object]') {
for (let prop in data._self) {
if (!data.hasOwnProperty(prop)) {
// _self.$set(data, prop, data._self[prop]);
data[prop] = data._self[prop];
}
}
@ -292,6 +285,8 @@ export default {
data.$options.staticRenderFns = _self.$options.staticRenderFns;
return _self.customRender.call(data);
};
} else if (_self.$scopedSlots.default) {
renderCell = () => _self.$scopedSlots.default(data);
}
if (!renderCell) {

View File

@ -226,7 +226,7 @@ export default {
filterPanel.table = table;
filterPanel.cell = cell;
filterPanel.column = column;
filterPanel.$mount(document.createElement('div'));
!this.$isServer && filterPanel.$mount(document.createElement('div'));
}
setTimeout(() => {
@ -239,6 +239,7 @@ export default {
},
handleMouseDown(event, column) {
if (this.$isServer) return;
if (column.children && column.children.length > 0) return;
/* istanbul ignore if */
if (this.draggingColumn && this.border) {
@ -329,6 +330,7 @@ export default {
},
handleMouseOut() {
if (this.$isServer) return;
document.body.style.cursor = '';
},

View File

@ -1,6 +1,4 @@
import { getScrollBarWidth } from './util';
let GUTTER_WIDTH;
import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
class TableLayout {
constructor(options) {
@ -21,11 +19,7 @@ class TableLayout {
this.viewportHeight = null; // Table Height - Scroll Bar Height
this.bodyHeight = null; // Table Height - Table Header Height
this.fixedBodyHeight = null; // Table Height - Table Header Height - Scroll Bar Height
if (GUTTER_WIDTH === undefined) {
GUTTER_WIDTH = getScrollBarWidth();
}
this.gutterWidth = GUTTER_WIDTH;
this.gutterWidth = scrollbarWidth();
for (let name in options) {
if (options.hasOwnProperty(name)) {
@ -44,7 +38,7 @@ class TableLayout {
updateScrollY() {
const height = this.height;
if (typeof height !== 'string' && typeof height !== 'number') return;
const bodyWrapper = this.table.$refs.bodyWrapper;
const bodyWrapper = this.table.bodyWrapper;
if (this.table.$el && bodyWrapper) {
const body = bodyWrapper.querySelector('.el-table__body');
this.scrollY = body.offsetHeight > bodyWrapper.offsetHeight;

View File

@ -18,7 +18,11 @@
:style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
</table-header>
</div>
<div class="el-table__body-wrapper" ref="bodyWrapper" :style="[bodyHeight]">
<el-scrollbar
class="el-table__body-wrapper"
ref="bodyWrapper"
:native="!virtualScrollbar"
:wrap-style="[bodyHeight]">
<table-body
:context="context"
:store="store"
@ -29,9 +33,9 @@
:style="{ width: layout.bodyWidth ? layout.bodyWidth - (layout.scrollY ? layout.gutterWidth : 0 ) + 'px' : '' }">
</table-body>
<div class="el-table__empty-block" v-if="!data || data.length === 0">
<span class="el-table__empty-text"><slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot></span>
<span class="el-table__empty-text"><slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot></span>
</div>
</div>
</el-scrollbar>
<div class="el-table__fixed" ref="fixedWrapper"
v-if="fixedColumns.length > 0"
:style="[
@ -130,6 +134,8 @@
width: [String, Number],
virtualScrollbar: Boolean,
height: [String, Number],
maxHeight: [String, Number],
@ -209,22 +215,22 @@
},
bindEvents() {
const { bodyWrapper, headerWrapper } = this.$refs;
const { headerWrapper } = this.$refs;
const refs = this.$refs;
bodyWrapper.addEventListener('scroll', function() {
this.bodyWrapper.addEventListener('scroll', function() {
if (headerWrapper) headerWrapper.scrollLeft = this.scrollLeft;
if (refs.fixedBodyWrapper) refs.fixedBodyWrapper.scrollTop = this.scrollTop;
if (refs.rightFixedBodyWrapper) refs.rightFixedBodyWrapper.scrollTop = this.scrollTop;
});
if (headerWrapper) {
mousewheel(headerWrapper, throttle(16, function(event) {
mousewheel(headerWrapper, throttle(16, event => {
const deltaX = event.deltaX;
if (deltaX > 0) {
bodyWrapper.scrollLeft = bodyWrapper.scrollLeft + 10;
this.bodyWrapper.scrollLeft += 10;
} else {
bodyWrapper.scrollLeft = bodyWrapper.scrollLeft - 10;
this.bodyWrapper.scrollLeft -= 10;
}
}));
}
@ -259,6 +265,10 @@
},
computed: {
bodyWrapper() {
return this.$refs.bodyWrapper.wrap;
},
shouldUpdateHeight() {
return typeof this.height === 'number' ||
this.fixedColumns.length > 0 ||

View File

@ -1,28 +1,3 @@
let scrollBarWidth;
export const getScrollBarWidth = () => {
if (scrollBarWidth !== undefined) return scrollBarWidth;
const outer = document.createElement('div');
outer.style.visibility = 'hidden';
outer.style.width = '100px';
outer.style.position = 'absolute';
outer.style.top = '-9999px';
document.body.appendChild(outer);
const widthNoScroll = outer.offsetWidth;
outer.style.overflow = 'scroll';
const inner = document.createElement('div');
inner.style.width = '100%';
outer.appendChild(inner);
const widthWithScroll = inner.offsetWidth;
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
};
export const getCell = function(event) {
let cell = event.target;
@ -99,7 +74,7 @@ export const getColumnByCell = function(table, cell) {
return null;
};
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
export const mousewheel = function(element, callback) {
if (element && element.addEventListener) {

View File

@ -31,7 +31,5 @@
"gulp-postcss": "^6.1.1",
"postcss-salad": "^1.0.5"
},
"dependencies": {
"vue-popup": "^0.2.9"
}
"dependencies": {}
}

View File

@ -0,0 +1,45 @@
@charset "UTF-8";
@import "./common/var.css";
@component-namespace el {
@b carousel {
@e item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: inline-block;
transition: .4s ease-in-out;
overflow: hidden;
@modifier card {
width: 50%;
z-index: calc(var(--index-normal) - 1);
&.is-in-stage {
cursor: pointer;
z-index: var(--index-normal);
&:hover .el-carousel__mask,
&.is-hover .el-carousel__mask {
opacity: 0.12;
}
}
&.is-active {
z-index: calc(var(--index-normal) + 1);
}
}
}
@e mask {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: var(--color-white);
opacity: 0.24;
transition: .2s;
}
}
}

View File

@ -0,0 +1,116 @@
@charset "UTF-8";
@import "./common/var.css";
@component-namespace el {
@b carousel {
overflow-x: hidden;
position: relative;
@e container {
position: relative;
height: 300px;
}
@e arrow {
border: none;
outline: none;
padding: 0;
margin: 0;
size: var(--carousel-arrow-size);
cursor: pointer;
transition: .3s;
border-radius: 50%;
background-color: var(--carousel-arrow-background);
color: var(--color-white);
position: absolute;
top: 50%;
z-index: 10;
transform: translateY(-50%);
text-align: center;
font-size: var(--carousel-arrow-font-size);
@modifier left {
left: 16px;
}
@modifier right {
right: 16px;
}
&:hover {
background-color: var(--carousel-arrow-hover-background);
}
& i {
cursor: pointer;
}
}
@e indicators {
position: absolute;
list-style: none;
bottom: 0;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
@modifier outside {
bottom: calc(var(--carousel-indicator-height) + var(--carousel-indicator-padding-vertical) * 2);
text-align: center;
position: static;
transform: none;
.el-carousel__indicator:hover button {
opacity: 0.64;
}
button {
background-color: var(--carousel-indicator-out-color);
opacity: 0.24;
}
}
}
@e indicator {
display: inline-block;
background-color: transparent;
padding: var(--carousel-indicator-padding-vertical) var(--carousel-indicator-padding-horizontal);
cursor: pointer;
&:hover button {
opacity: 0.72;
}
@when active {
button {
opacity: 1;
}
}
}
@e button {
display: block;
opacity: 0.48;
size: var(--carousel-indicator-width) var(--carousel-indicator-height);
background-color: var(--color-white);
border: none;
outline: none;
padding: 0;
margin: 0;
cursor: pointer;
transition: .3s;
}
}
.carousel-arrow-left-enter,
.carousel-arrow-left-leave-active {
transform: translateY(-50%) translateX(-10px);
opacity: 0;
}
.carousel-arrow-right-enter,
.carousel-arrow-right-leave-active {
transform: translateY(-50%) translateX(10px);
opacity: 0;
}
}

View File

@ -0,0 +1,52 @@
@charset "UTF-8";
@import "./common/var.css";
@component-namespace el {
@b collapse {
border: 1px solid var(--collapse-border-color);
border-radius: var(--collapse-border-radius);
}
@b collapse-item {
@e header {
height: var(--collapse-header-height);
line-height: @height;
padding-left: 15px;
background-color: var(--collapse-header-fill);
color: var(--collapse-header-color);
cursor: pointer;
border-bottom: 1px solid var(--collapse-border-color);
font-size: var(--collapse-header-size);
@e arrow {
margin-right: 8px;
transition: transform .3s;
}
}
@e wrap {
will-change: height;
background-color: var(--collapse-content-fill);
transition: height .3s cubic-bezier(0.215, 0.61, 0.355, 1);
overflow: hidden;
box-sizing: border-box;
border-bottom: 1px solid var(--collapse-border-color);
}
@e content {
padding: 10px 15px;
font-size: var(--collapse-content-size);
color: var(--collapse-content-color);
line-height: 1.769230769230769;
}
@when active {
.el-collapse-item__header__arrow {
transform: rotate(90deg);
}
}
&:last-child {
margin-bottom: -1px;
}
}
}

View File

@ -0,0 +1,33 @@
.v-modal-enter {
animation: v-modal-in .2s ease;
}
.v-modal-leave {
animation: v-modal-out .2s ease forwards;
}
@keyframes v-modal-in {
0% {
opacity: 0;
}
100% {
}
}
@keyframes v-modal-out {
0% {
}
100% {
opacity: 0;
}
}
.v-modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.5;
background: #000;
}

View File

@ -544,4 +544,34 @@
--------------------------*/
--loading-spinner-size: 42px;
--loading-fullscreen-spinner-size: 50px;
/* Scrollbar
--------------------------*/
--scrollbar-background-color: rgba(#99a9bf, .3);
--scrollbar-hover-background-color: rgba(#99a9bf, .5);
/* Carousel
--------------------------*/
--carousel-arrow-font-size: 12px;
--carousel-arrow-size: 36px;
--carousel-arrow-background: rgba(31, 45, 61, 0.11);
--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23);
--carousel-indicator-width: 30px;
--carousel-indicator-height: 2px;
--carousel-indicator-padding-horizontal: 4px;
--carousel-indicator-padding-vertical: 12px;
--carousel-indicator-out-color: var(--border-color-hover);
/* Collapse
--------------------------*/
--collapse-border-color: #e0e6ed;
--collapse-header-height: 43px;
--collapse-border-radius: 0;
--collapse-header-padding: 20px;
--collapse-header-fill: #fff;
--collapse-header-color: #475669;
--collapse-header-size: 13px;
--collapse-content-fill: #f9fafc;
--collapse-content-size: 13px;
--collapse-content-color: #1f2d3d;
}

View File

@ -4,22 +4,21 @@
@b time-spinner {
&.has-seconds {
.el-time-spinner__wrapper {
width: calc(100% / 3);
width: 33%;
}
.el-time-spinner__wrapper:nth-child(2) {
padding-left: 1%;
}
}
@e wrapper {
height: 190px;
overflow: hidden;
max-height: 190px;
overflow: auto;
display: inline-block;
width: 50%;
vertical-align: top;
position: relative;
-ms-overflow-style: none;
&:hover {
overflow-y: auto;
}
}
@e list {

View File

@ -1,6 +1,6 @@
@charset "UTF-8";
@import "./common/var.css";
@import "vue-popup/lib/popup.css";
@import "./common/popup.css";
@component-namespace el {

View File

@ -40,3 +40,7 @@
@import "./rate.css";
@import "./steps.css";
@import "./step.css";
@import "./scrollbar.css";
@import "./carousel.css";
@import "./carousel-item.css";
@import "./collapse.css";

View File

@ -1,8 +1,8 @@
@charset "UTF-8";
@import "./common/var.css";
@import "./common/popup.css";
@import "./button.css";
@import "./input.css";
@import "vue-popup/lib/popup.css";
@component-namespace el {

View File

@ -0,0 +1,68 @@
@component-namespace el {
@b scrollbar {
overflow: hidden;
position: relative;
&:hover,
&:active,
&:focus {
.el-scrollbar__bar {
opacity: 1;
transition: opacity 340ms ease-out;
}
}
@e wrap {
overflow: scroll;
@m hidden-default {
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
}
@e thumb {
position: relative;
display: block;
size: 0;
cursor: pointer;
border-radius: inherit;
background-color: var(--scrollbar-background-color);
transition: .3s background-color;
&:hover {
background-color: var(--scrollbar-hover-background-color);
}
}
@e bar {
position: absolute;
right: 2px;
bottom: 2px;
z-index: 1;
border-radius: 4px;
opacity: 0;
transition: opacity 120ms ease-out;
@when vertical {
width: 6px;
top: 2px;
> div {
width: 100%;
}
}
@when horizontal {
height: 6px;
left: 2px;
> div {
height: 100%;
}
}
}
}
}

View File

@ -43,14 +43,16 @@
font-size: var(--select-font-size);
}
@b select-dropdown__wrap {
max-height: var(--select-dropdown-max-height);
width: 100%;
}
@b select-dropdown__list {
list-style: none;
padding: var(--select-dropdown-padding);
margin: 0;
width: 100%;
max-height: var(--select-dropdown-max-height);
box-sizing: border-box;
overflow-y: auto;
@when empty {
padding: 0;

View File

@ -9,12 +9,7 @@
.time-select .el-picker-panel__content {
max-height: 200px;
overflow: hidden;
margin: 0;
&:hover {
overflow-y: auto;
}
}
.time-select-item {

View File

@ -113,7 +113,7 @@ export default {
},
mounted() {
window.addEventListener('message', (event) => {
!this.$isServer && window.addEventListener('message', (event) => {
var targetOrigin = new URL(this.action).origin;
if (event.origin !== targetOrigin) {
return false;
@ -158,7 +158,7 @@ export default {
on-change={this.handleChange}
accept={this.accept}>
</input>
<input type="hidden" name="documentDomain" value={document.domain} />
<input type="hidden" name="documentDomain" value={ this.$isServer ? '' : document.domain } />
<span ref="data"></span>
</form>
{!this.showCover ? this.$slots.default : cover}

View File

@ -209,7 +209,7 @@ export default {
ref: 'upload-inner'
};
var uploadComponent = typeof FormData !== 'undefined'
var uploadComponent = this.$isServer ? '' : typeof FormData !== 'undefined'
? <upload {...props}>{this.$slots.default}</upload>
: <iframeUpload {...props}>{this.$slots.default}</iframeUpload>;

View File

@ -55,6 +55,11 @@ import Card from '../packages/card';
import Rate from '../packages/rate';
import Steps from '../packages/steps';
import Step from '../packages/step';
import Carousel from '../packages/carousel';
import Scrollbar from '../packages/scrollbar';
import CarouselItem from '../packages/carousel-item';
import Collapse from '../packages/collapse';
import CollapseItem from '../packages/collapse-item';
import locale from 'element-ui/src/locale';
const install = function(Vue, opts = {}) {
@ -113,6 +118,11 @@ const install = function(Vue, opts = {}) {
Vue.component(Rate.name, Rate);
Vue.component(Steps.name, Steps);
Vue.component(Step.name, Step);
Vue.component(Carousel.name, Carousel);
Vue.component(Scrollbar.name, Scrollbar);
Vue.component(CarouselItem.name, CarouselItem);
Vue.component(Collapse.name, Collapse);
Vue.component(CollapseItem.name, CollapseItem);
Vue.use(Loading.directive);
@ -188,5 +198,10 @@ module.exports = {
Card,
Rate,
Steps,
Step
Step,
Carousel,
Scrollbar,
CarouselItem,
Collapse,
CollapseItem
};

View File

@ -1,9 +1,10 @@
import { on } from 'wind-dom/src/event';
import Vue from 'vue';
import { on } from 'element-ui/src/utils/dom';
const nodeList = [];
const ctx = '@@clickoutsideContext';
on(document, 'click', e => {
!Vue.prototype.$isServer && on(document, 'click', e => {
nodeList.forEach(node => node[ctx].documentHandler(e));
});
/**

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