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 sudo: false
language: node_js language: node_js
node_js: stable node_js: stable
cache:
directories:
- $HOME/.npm
- $HOME/.yarn-cache
before_install: 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_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_USER="$(git log --no-merges -n 1 --format=%an)"
- export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)" - export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)"
install: yarn install
script: yarn run test
after_success: after_success:
- sh build/deploy-ci.sh - sh build/deploy-ci.sh
- cat ./test/unit/coverage/lcov.info | ./node_modules/.bin/coveralls - cat ./test/unit/coverage/lcov.info | ./node_modules/.bin/coveralls

View File

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

View File

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

View File

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

View File

@ -53,5 +53,10 @@
"card": "./packages/card/index.js", "card": "./packages/card/index.js",
"rate": "./packages/rate/index.js", "rate": "./packages/rate/index.js",
"steps": "./packages/steps/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> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { return {

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. 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[] | — | — | | 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 | — | — | | 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 ### shortcuts
| Attribute | Description | Type | Accepted Values | Default | | 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 ### Form Methods
| Method | Description | | Method | Description | Parameters |
| ---- | ---- | | ---- | ---- | ---- |
| validate(cb) | the method to validate the whole form | | validate | the method to validate the whole form | Function(callback: Function(boolean)) |
| validateField(prop, cb) | the method to validate a certain form item | | validateField | the method to validate a certain form item | Function(prop: string, callback: Function(errorMessage: string)) |
| resetFields | reset all the fields to initial value and remove validation result | | resetFields | reset all the fields and remove validation result | — |
### Form-Item Attributes ### Form-Item Attributes

View File

@ -117,7 +117,7 @@ Add more modules based on your scenario.
``` ```
::: :::
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { return {

View File

@ -45,7 +45,7 @@ Typical configurations for these config files are:
}, },
"dependencies": { "dependencies": {
"element-ui": "^1.0.0", "element-ui": "^1.0.0",
"vue": "^2.0.5" "vue": "^2.1.6"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.0.0", "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"> width="120">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
:context="_self"
fixed="right" fixed="right"
label="Operations" label="Operations"
width="120"> width="120">
<span> <template scope="scope">
<el-button @click="handleClick" type="text" size="small">Detail</el-button> <el-button @click="handleClick" type="text" size="small">Detail</el-button>
<el-button type="text" size="small">Edit</el-button> <el-button type="text" size="small">Edit</el-button>
</span> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -781,19 +779,17 @@ When the the data is dynamically changed, you might want the table to have a max
width="120"> width="120">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
:context="_self"
fixed="right" fixed="right"
label="Operations" label="Operations"
width="120"> width="120">
<span> <template scope="scope">
<el-button <el-button
@click.native.prevent="deleteRow($index, tableData4)" @click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text" type="text"
size="small"> size="small">
Remove Remove
</el-button> </el-button>
</span> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -1045,13 +1041,12 @@ Single row selection is supported.
You can also select multiple rows. 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 ```html
<template> <template>
<el-table <el-table
:data="tableData3" :data="tableData3"
border border
selection-mode="multiple"
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange"> @selection-change="handleSelectionChange">
<el-table-column <el-table-column
@ -1059,10 +1054,9 @@ You can also select multiple rows.
width="55"> width="55">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
label="Date" label="Date"
width="120"> width="120">
<div>{{ row.date }}</div> <template scope="scope">{{ scope.row.date }}</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
property="name" property="name"
@ -1219,9 +1213,12 @@ Filter the table to find desired data.
label="Tag" label="Tag"
width="100" width="100"
:filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]" :filters="[{ text: 'Home', value: 'Home' }, { text: 'Office', value: 'Office' }]"
:filter-method="filterTag" :filter-method="filterTag">
inline-template> <template scope="scope">
<el-tag :type="row.tag === 'Home' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag> <el-tag
:type="scope.row.tag === 'Home' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -1269,7 +1266,7 @@ Filter the table to find desired data.
### Custom column template ### Custom column template
Customize table column so it can be integrated with other components. 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 ```html
<template> <template>
<el-table <el-table
@ -1277,43 +1274,38 @@ Customize table column so it can be integrated with other components.
border border
style="width: 100%"> style="width: 100%">
<el-table-column <el-table-column
inline-template
label="Date" label="Date"
width="180"> width="180">
<div> <template scope="scope">
<el-icon name="time"></el-icon> <el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span> <span style="margin-left: 10px">{{ scope.row.date }}</span>
</div> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
label="Name" label="Name"
width="180"> width="180">
<template scope="scope">
<el-popover trigger="hover" placement="top"> <el-popover trigger="hover" placement="top">
<p>Name: {{ row.name }}</p> <p>Name: {{ scope.row.name }}</p>
<p>Addr: {{ row.address }}</p> <p>Addr: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag> <el-tag>{{ scope.row.name }}</el-tag>
</div> </div>
</el-popover> </el-popover>
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:context="_self" :context="_self"
inline-template
label="Operations"> label="Operations">
<div> <template scope="scope">
<el-button <el-button
size="small" size="small"
@click="handleEdit($index, row)"> @click="handleEdit(scope.$index, scope.row)">Edit</el-button>
Edit
</el-button>
<el-button <el-button
size="small" size="small"
type="danger" type="danger"
@click="handleDelete($index, row)"> @click="handleDelete(scope.$index, scope.row)">Delete</el-button>
Delete </template>
</el-button>
</div>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </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 | | 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 | | 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 | - | | | 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 ### Table Events
| Event Name | Description | Parameters | | 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 | | expand | triggers when user expands or collapses a row | row, expanded |
### Table Methods ### Table Methods
| Method | Description | Parameter | | Method | Description | Parameters |
|------|--------|-------| |------|--------|-------|
| clearSelection | clear selection, might be useful when `reserve-selection` is on | selection | | 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 | | 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 | | 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) | — | — | | 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 | | 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 | | 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 | — | | 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 | — | — | | 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 | | end | end time | string | — | 18:00 |
| step | time step | string | — | 00:30 | | step | time step | string | — | 00:30 |
| minTime | minimum time, any time before this time will be disabled | string | — | 00:00 | | 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 ### Time Picker Options
| Attribute | Description | Type | Accepted Values | Default | | Attribute | Description | Type | Accepted Values | Default |

View File

@ -1,5 +1,5 @@
<script> <script>
import { addClass } from 'wind-dom/src/class'; import { addClass } from 'element-ui/src/utils/dom';
export default { export default {
data() { data() {
return { 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[] | - | - | | shortcuts | 设置快捷选项,需要传入 { text, onClick } 对象用法参考 demo 或下表 | Object[] | - | - |
| disabledDate | 设置禁用状态,参数为当前日期,要求返回 Boolean | Function | - | - | | disabledDate | 设置禁用状态,参数为当前日期,要求返回 Boolean | Function | - | - |
| firstDayOfWeek | 周起始日 | Number | 1 到 7 | 7 |
### Shortcuts ### Shortcuts
| 参数 | 说明 | 类型 | 可选值 | 默认值 | | 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

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

View File

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

View File

@ -587,15 +587,13 @@
width="120"> width="120">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
:context="_self"
fixed="right" fixed="right"
label="操作" label="操作"
width="100"> width="100">
<span> <template scope="scope">
<el-button @click="handleClick" type="text" size="small">查看</el-button> <el-button @click="handleClick" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button> <el-button type="text" size="small">编辑</el-button>
</span> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -797,19 +795,17 @@
width="120"> width="120">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
:context="_self"
fixed="right" fixed="right"
label="操作" label="操作"
width="120"> width="120">
<span> <template scope="scope">
<el-button <el-button
@click.native.prevent="deleteRow($index, tableData4)" @click.native.prevent="deleteRow(scope.$index, tableData4)"
type="text" type="text"
size="small"> size="small">
移除 移除
</el-button> </el-button>
</span> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -1061,7 +1057,7 @@
选择多行数据时使用 Checkbox。 选择多行数据时使用 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 ```html
<template> <template>
<el-table <el-table
@ -1074,10 +1070,9 @@
width="55"> width="55">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
label="日期" label="日期"
width="120"> width="120">
<div>{{ row.date }}</div> <template scope="scope">{{ scope.row.date }}</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="name" prop="name"
@ -1234,9 +1229,12 @@
label="标签" label="标签"
width="100" width="100"
:filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]" :filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
:filter-method="filterTag" :filter-method="filterTag">
inline-template> <template scope="scope">
<el-tag :type="row.tag === '家' ? 'primary' : 'success'" close-transition>{{row.tag}}</el-tag> <el-tag
:type="scope.row.tag === '家' ? 'primary' : 'success'"
close-transition>{{scope.row.tag}}</el-tag>
</template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </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 ```html
<template> <template>
<el-table <el-table
@ -1292,43 +1290,36 @@
border border
style="width: 100%"> style="width: 100%">
<el-table-column <el-table-column
inline-template
label="日期" label="日期"
width="180"> width="180">
<div> <template scope="scope">
<el-icon name="time"></el-icon> <el-icon name="time"></el-icon>
<span style="margin-left: 10px">{{ row.date }}</span> <span style="margin-left: 10px">{{ scope.row.date }}</span>
</div> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
inline-template
label="姓名" label="姓名"
width="180"> width="180">
<template scope="scope">
<el-popover trigger="hover" placement="top"> <el-popover trigger="hover" placement="top">
<p>姓名: {{ row.name }}</p> <p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ row.address }}</p> <p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<el-tag>{{ row.name }}</el-tag> <el-tag>{{ scope.row.name }}</el-tag>
</div> </div>
</el-popover> </el-popover>
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column label="操作">
:context="_self" <template scope="scope">
inline-template
label="操作">
<div>
<el-button <el-button
size="small" size="small"
@click="handleEdit($index, row)"> @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
编辑
</el-button>
<el-button <el-button
size="small" size="small"
type="danger" type="danger"
@click="handleDelete($index, row)"> @click="handleDelete(scope.$index, scope.row)">删除</el-button>
删除 </template>
</el-button>
</div>
</el-table-column> </el-table-column>
</el-table> </el-table>
</template> </template>
@ -1454,6 +1445,8 @@
| empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | - | 暂无数据 | | empty-text | 空数据时显示的文本内容,也可以通过 `slot="empty"` 设置 | String | - | 暂无数据 |
| default-expand-all | 是否默认展开所有行,当 Table 中存在 type="expand" 的 Column 的时候有效 | Boolean | - | false | | default-expand-all | 是否默认展开所有行,当 Table 中存在 type="expand" 的 Column 的时候有效 | Boolean | - | false |
| expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。| Array | - | | | expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。| Array | - | |
| virtual-scrollbar | 启用虚拟滚动条 | Boolean | - | false |
### Table Events ### Table Events
| 事件名 | 说明 | 参数 | | 事件名 | 说明 | 参数 |
@ -1495,8 +1488,6 @@
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true | | resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | Function(row, column) | — | — | | formatter | 用来格式化内容 | Function(row, column) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | Boolean | — | false | | 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 | | align | 对齐方式 | String | left/center/right | left |
| header-align | 表头对齐方式,若不设置该项,则使用表格的对齐方式 | String | left/center/right | — | | header-align | 表头对齐方式,若不设置该项,则使用表格的对齐方式 | String | left/center/right | — |
| class-name | 列的 className | string | — | — | | class-name | 列的 className | string | — | — |

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -49,7 +49,7 @@
<script type="text/babel"> <script type="text/babel">
import Locale from 'element-ui/src/mixins/locale'; 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 { export default {
props: { props: {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
import Vue from 'vue'; 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')); let Mask = Vue.extend(require('./loading.vue'));
exports.install = Vue => { exports.install = Vue => {
if (Vue.prototype.$isServer) return;
let toggleLoading = (el, binding) => { let toggleLoading = (el, binding) => {
if (binding.value) { if (binding.value) {
Vue.nextTick(() => { Vue.nextTick(() => {

View File

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

View File

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

View File

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

View File

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

View File

@ -24,11 +24,11 @@
</template> </template>
<script type="text/babel"> <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 Locale from 'element-ui/src/mixins/locale';
import ElInput from 'element-ui/packages/input'; import ElInput from 'element-ui/packages/input';
import ElButton from 'element-ui/packages/button'; 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'; import { t } from 'element-ui/src/locale';
let typeMap = { let typeMap = {

View File

@ -1,5 +1,5 @@
import Vue from 'vue'; 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 MessageConstructor = Vue.extend(require('./main.vue'));
let instance; let instance;
@ -7,6 +7,7 @@ let instances = [];
let seed = 1; let seed = 1;
var Message = function(options) { var Message = function(options) {
if (Vue.prototype.$isServer) return;
options = options || {}; options = options || {};
if (typeof options === 'string') { if (typeof options === 'string') {
options = { options = {

View File

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

View File

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

View File

@ -17,7 +17,7 @@
<script> <script>
import Popper from 'element-ui/src/utils/vue-popper'; 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 { export default {
name: 'el-popover', name: 'el-popover',

View File

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

View File

@ -24,7 +24,7 @@
</template> </template>
<script type="text/babel"> <script type="text/babel">
import { hasClass } from 'wind-dom/src/class'; import { hasClass } from 'element-ui/src/utils/dom';
export default { export default {
name: 'el-rate', 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", "license": "MIT",
"repository": "https://github.com/ElemeFE/element/tree/master/packages/select", "repository": "https://github.com/ElemeFE/element/tree/master/packages/select",
"devDependencies": { "devDependencies": {
"throttle-debounce": "^1.0.1", "throttle-debounce": "^1.0.1"
"wind-dom": "0.0.3"
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,7 +18,11 @@
:style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }"> :style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
</table-header> </table-header>
</div> </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 <table-body
:context="context" :context="context"
:store="store" :store="store"
@ -31,7 +35,7 @@
<div class="el-table__empty-block" v-if="!data || data.length === 0"> <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>
</div> </el-scrollbar>
<div class="el-table__fixed" ref="fixedWrapper" <div class="el-table__fixed" ref="fixedWrapper"
v-if="fixedColumns.length > 0" v-if="fixedColumns.length > 0"
:style="[ :style="[
@ -130,6 +134,8 @@
width: [String, Number], width: [String, Number],
virtualScrollbar: Boolean,
height: [String, Number], height: [String, Number],
maxHeight: [String, Number], maxHeight: [String, Number],
@ -209,22 +215,22 @@
}, },
bindEvents() { bindEvents() {
const { bodyWrapper, headerWrapper } = this.$refs; const { headerWrapper } = this.$refs;
const refs = this.$refs; const refs = this.$refs;
bodyWrapper.addEventListener('scroll', function() { this.bodyWrapper.addEventListener('scroll', function() {
if (headerWrapper) headerWrapper.scrollLeft = this.scrollLeft; if (headerWrapper) headerWrapper.scrollLeft = this.scrollLeft;
if (refs.fixedBodyWrapper) refs.fixedBodyWrapper.scrollTop = this.scrollTop; if (refs.fixedBodyWrapper) refs.fixedBodyWrapper.scrollTop = this.scrollTop;
if (refs.rightFixedBodyWrapper) refs.rightFixedBodyWrapper.scrollTop = this.scrollTop; if (refs.rightFixedBodyWrapper) refs.rightFixedBodyWrapper.scrollTop = this.scrollTop;
}); });
if (headerWrapper) { if (headerWrapper) {
mousewheel(headerWrapper, throttle(16, function(event) { mousewheel(headerWrapper, throttle(16, event => {
const deltaX = event.deltaX; const deltaX = event.deltaX;
if (deltaX > 0) { if (deltaX > 0) {
bodyWrapper.scrollLeft = bodyWrapper.scrollLeft + 10; this.bodyWrapper.scrollLeft += 10;
} else { } else {
bodyWrapper.scrollLeft = bodyWrapper.scrollLeft - 10; this.bodyWrapper.scrollLeft -= 10;
} }
})); }));
} }
@ -259,6 +265,10 @@
}, },
computed: { computed: {
bodyWrapper() {
return this.$refs.bodyWrapper.wrap;
},
shouldUpdateHeight() { shouldUpdateHeight() {
return typeof this.height === 'number' || return typeof this.height === 'number' ||
this.fixedColumns.length > 0 || 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) { export const getCell = function(event) {
let cell = event.target; let cell = event.target;
@ -99,7 +74,7 @@ export const getColumnByCell = function(table, cell) {
return null; 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) { export const mousewheel = function(element, callback) {
if (element && element.addEventListener) { if (element && element.addEventListener) {

View File

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

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-spinner-size: 42px;
--loading-fullscreen-spinner-size: 50px; --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 { @b time-spinner {
&.has-seconds { &.has-seconds {
.el-time-spinner__wrapper { .el-time-spinner__wrapper {
width: calc(100% / 3); width: 33%;
}
.el-time-spinner__wrapper:nth-child(2) {
padding-left: 1%;
} }
} }
@e wrapper { @e wrapper {
height: 190px; max-height: 190px;
overflow: hidden; overflow: auto;
display: inline-block; display: inline-block;
width: 50%; width: 50%;
vertical-align: top; vertical-align: top;
position: relative; position: relative;
-ms-overflow-style: none;
&:hover {
overflow-y: auto;
}
} }
@e list { @e list {

View File

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

View File

@ -40,3 +40,7 @@
@import "./rate.css"; @import "./rate.css";
@import "./steps.css"; @import "./steps.css";
@import "./step.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"; @charset "UTF-8";
@import "./common/var.css"; @import "./common/var.css";
@import "./common/popup.css";
@import "./button.css"; @import "./button.css";
@import "./input.css"; @import "./input.css";
@import "vue-popup/lib/popup.css";
@component-namespace el { @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); font-size: var(--select-font-size);
} }
@b select-dropdown__wrap {
max-height: var(--select-dropdown-max-height);
width: 100%;
}
@b select-dropdown__list { @b select-dropdown__list {
list-style: none; list-style: none;
padding: var(--select-dropdown-padding); padding: var(--select-dropdown-padding);
margin: 0; margin: 0;
width: 100%;
max-height: var(--select-dropdown-max-height);
box-sizing: border-box; box-sizing: border-box;
overflow-y: auto;
@when empty { @when empty {
padding: 0; padding: 0;

View File

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

View File

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

View File

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

View File

@ -55,6 +55,11 @@ import Card from '../packages/card';
import Rate from '../packages/rate'; import Rate from '../packages/rate';
import Steps from '../packages/steps'; import Steps from '../packages/steps';
import Step from '../packages/step'; 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'; import locale from 'element-ui/src/locale';
const install = function(Vue, opts = {}) { const install = function(Vue, opts = {}) {
@ -113,6 +118,11 @@ const install = function(Vue, opts = {}) {
Vue.component(Rate.name, Rate); Vue.component(Rate.name, Rate);
Vue.component(Steps.name, Steps); Vue.component(Steps.name, Steps);
Vue.component(Step.name, Step); 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); Vue.use(Loading.directive);
@ -188,5 +198,10 @@ module.exports = {
Card, Card,
Rate, Rate,
Steps, 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 nodeList = [];
const ctx = '@@clickoutsideContext'; const ctx = '@@clickoutsideContext';
on(document, 'click', e => { !Vue.prototype.$isServer && on(document, 'click', e => {
nodeList.forEach(node => node[ctx].documentHandler(e)); nodeList.forEach(node => node[ctx].documentHandler(e));
}); });
/** /**

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