diff --git a/components.json b/components.json
index 966d4a473..314321185 100644
--- a/components.json
+++ b/components.json
@@ -58,5 +58,6 @@
"scrollbar": "./packages/scrollbar/index.js",
"carousel-item": "./packages/carousel-item/index.js",
"collapse": "./packages/collapse/index.js",
- "collapse-item": "./packages/collapse-item/index.js"
+ "collapse-item": "./packages/collapse-item/index.js",
+ "cascader": "./packages/cascader/index.js"
}
diff --git a/examples/docs/en-US/cascader.md b/examples/docs/en-US/cascader.md
new file mode 100644
index 000000000..01bc1fc8f
--- /dev/null
+++ b/examples/docs/en-US/cascader.md
@@ -0,0 +1 @@
+## cascader
diff --git a/examples/docs/zh-CN/cascader.md b/examples/docs/zh-CN/cascader.md
new file mode 100644
index 000000000..8739e22b6
--- /dev/null
+++ b/examples/docs/zh-CN/cascader.md
@@ -0,0 +1,109 @@
+
+
+## 级联选择
+
+需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等。
+
+从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。
+
+### 基本使用
+
+:::demo
+```html
+
+```
+:::
+
+### 默认值
+
+:::demo
+```html
+
+```
+:::
+
+### 移入展开
+
+:::demo
+```html
+
+```
+:::
+
+### 选择即改变
+
+:::demo
+```html
+
+```
+:::
+
+### 可搜索
+
+:::demo
+```html
+
+```
+:::
\ No newline at end of file
diff --git a/examples/nav.config.json b/examples/nav.config.json
index 9f78e055f..fdeb534a1 100644
--- a/examples/nav.config.json
+++ b/examples/nav.config.json
@@ -215,6 +215,10 @@
{
"path": "/collapse",
"title": "Collapse 折叠面板"
+ },
+ {
+ "path": "/cascader",
+ "title": "Cascader 级联选择"
}
]
}
@@ -437,6 +441,10 @@
{
"path": "/collapse",
"title": "Collapse"
+ },
+ {
+ "path": "/cascader",
+ "title": "Cascader"
}
]
}
diff --git a/packages/cascader/cooking.conf.js b/packages/cascader/cooking.conf.js
new file mode 100644
index 000000000..3bbec53de
--- /dev/null
+++ b/packages/cascader/cooking.conf.js
@@ -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: 'ElCascader',
+ extends: ['vue2'],
+ alias: config.alias,
+ externals: { vue: config.vue }
+});
+
+module.exports = cooking.resolve();
diff --git a/packages/cascader/index.js b/packages/cascader/index.js
new file mode 100644
index 000000000..68163ac5e
--- /dev/null
+++ b/packages/cascader/index.js
@@ -0,0 +1,8 @@
+import Cascader from './src/main';
+
+/* istanbul ignore next */
+Cascader.install = function(Vue) {
+ Vue.component(Cascader.name, Cascader);
+};
+
+export default Cascader;
diff --git a/packages/cascader/package.json b/packages/cascader/package.json
new file mode 100644
index 000000000..65e1961f9
--- /dev/null
+++ b/packages/cascader/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "element-cascader",
+ "version": "0.0.0",
+ "description": "A cascader component for Vue.js.",
+ "keywords": [
+ "element",
+ "vue",
+ "component"
+ ],
+ "main": "./lib/index.js",
+ "repository": "https://github.com/ElemeFE/element/tree/master/packages/cascader",
+ "author": "elemefe",
+ "license": "MIT",
+ "dependencies": {}
+}
diff --git a/packages/cascader/src/main.vue b/packages/cascader/src/main.vue
new file mode 100644
index 000000000..47e3eaaa6
--- /dev/null
+++ b/packages/cascader/src/main.vue
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+ {{displayValue}}
+
+
+
+
diff --git a/packages/cascader/src/menu.vue b/packages/cascader/src/menu.vue
new file mode 100644
index 000000000..927431d96
--- /dev/null
+++ b/packages/cascader/src/menu.vue
@@ -0,0 +1,133 @@
+
\ No newline at end of file
diff --git a/packages/theme-default/src/cascader.css b/packages/theme-default/src/cascader.css
index a79fe34e2..10370d653 100644
--- a/packages/theme-default/src/cascader.css
+++ b/packages/theme-default/src/cascader.css
@@ -3,42 +3,136 @@
@import "./common/var.css";
/*@import "./core/dropdown.css";*/
-@component-namespace element {
+@component-namespace el {
@b cascader {
display: inline-block;
position: relative;
+ background-color: #fff;
- @e dropdown {
- background-color: var(--cascader-menu-fill);
- border: var(--cascader-menu-border);
- border-radius: var(--cascader-menu-radius);
- box-shadow: var(--cascader-menu-submenu-shadow);
- margin-top: 5px;
- max-height: var(--cascader-height);
+ .el-input,
+ .el-input__inner {
+ cursor: pointer;
+ background-color: transparent;
+ z-index: 1;
+ }
+
+ .el-input__icon {
+ transition: none;
+ }
+
+ .el-icon-caret-bottom {
+ transition: transform .3s;
+
+ @when reverse {
+ transform: rotateZ(180deg);
+ }
+ }
+
+ @e label {
position: absolute;
+ left: 0;
+ top: 0;
+ height: var(--input-height);
+ line-height: @height;
+ padding: 0 15px 0 10px;
+ color: var(--input-color);
+ width: 100%;
white-space: nowrap;
- z-index: 10;
- }
-
- @e wrap {
+ text-overflow: ellipsis;
overflow: hidden;
+ box-sizing: border-box;
+ cursor: pointer;
+ }
+ }
+
+ @b cascader-menus {
+ white-space: nowrap;
+ background: #fff;
+ position: absolute;
+ margin: 5px 0;
+ z-index: 1001;
+ border: var(--select-dropdown-border);
+ border-radius: var(--border-radius-small);
+ overflow: hidden;
+ box-shadow: var(--select-dropdown-shadow);
+ }
+
+ @b cascader-menu {
+ display: inline-block;
+ vertical-align: top;
+ height: 180px;
+ overflow: auto;
+ border-right: var(--select-dropdown-border);
+ background-color: var(--select-dropdown-background);
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ min-width: 110px;
+
+ &:last-child {
+ border-right: 0;
}
- @e menu {
- border: 0;
- box-shadow: none;
- display: inline-block;
- margin: 0;
+ @e item {
+ font-size: var(--select-font-size);
+ padding: 8px 30px 8px 10px;
position: relative;
- vertical-align: top;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: var(--select-option-color);
+ height: var(--select-option-height);
+ line-height: 1.5;
+ box-sizing: border-box;
+ cursor: pointer;
- &::before {
- border-left: var(--cascader-menu-border);
- content: " ";
- height: var(--cascader-height);
- left: 0;
- position: absolute;
+ @e keyword {
+ color: var(--color-danger);
+ }
+
+ @m extensible {
+ &:after {
+ font-family: 'element-icons';
+ content: "\e602";
+ font-size: 12px;
+ transform: scale(0.8);
+ color: rgb(191, 203, 217);
+ position: absolute;
+ right: 10px;
+ margin-top: 1px;
+ }
+ }
+
+ @when disabled {
+ color: var(--select-option-disabled-color);
+ cursor: not-allowed;
+
+ &:hover {
+ background-color: var(--color-white);
+ }
+ }
+
+ @when active {
+ color: var(--color-white);
+ background-color: var(--select-option-selected);
+
+ &.hover {
+ background-color: var(--select-option-selected-hover);
+ }
+ }
+
+ &:hover {
+ background-color: var(--select-option-hover-background);
+ }
+
+ &.selected {
+ color: var(--color-white);
+ background-color: var(--select-option-selected);
+
+ &.hover {
+ background-color: var(--select-option-selected-hover);
+ }
}
}
}
diff --git a/packages/theme-default/src/index.css b/packages/theme-default/src/index.css
index 544ee48d7..67e499d73 100644
--- a/packages/theme-default/src/index.css
+++ b/packages/theme-default/src/index.css
@@ -44,3 +44,4 @@
@import "./carousel.css";
@import "./carousel-item.css";
@import "./collapse.css";
+@import "./cascader.css";
diff --git a/src/index.js b/src/index.js
index cfa8c6c8d..36fd0fefc 100644
--- a/src/index.js
+++ b/src/index.js
@@ -60,6 +60,7 @@ import Scrollbar from '../packages/scrollbar';
import CarouselItem from '../packages/carousel-item';
import Collapse from '../packages/collapse';
import CollapseItem from '../packages/collapse-item';
+import Cascader from '../packages/cascader';
import locale from 'element-ui/src/locale';
const components = [
@@ -118,7 +119,8 @@ const components = [
Scrollbar,
CarouselItem,
Collapse,
- CollapseItem
+ CollapseItem,
+ Cascader
];
const install = function(Vue, opts = {}) {
@@ -211,5 +213,6 @@ module.exports = {
Scrollbar,
CarouselItem,
Collapse,
- CollapseItem
+ CollapseItem,
+ Cascader
};
diff --git a/src/utils/vue-popper.js b/src/utils/vue-popper.js
index 18c02c8f6..0b5ee1504 100644
--- a/src/utils/vue-popper.js
+++ b/src/utils/vue-popper.js
@@ -83,6 +83,7 @@ export default {
this.$slots.reference[0]) {
reference = this.referenceElm = this.$slots.reference[0].elm;
}
+
if (!popper || !reference) return;
if (this.visibleArrow) this.appendArrow(popper);
if (this.appendToBody) document.body.appendChild(this.popperElm);
diff --git a/test/unit/specs/cascader.spec.js b/test/unit/specs/cascader.spec.js
new file mode 100644
index 000000000..2d6a868e7
--- /dev/null
+++ b/test/unit/specs/cascader.spec.js
@@ -0,0 +1,15 @@
+import { createTest, destroyVM } from '../util';
+import Cascader from 'packages/cascader';
+
+describe('Cascader', () => {
+ let vm;
+ afterEach(() => {
+ destroyVM(vm);
+ });
+
+ it('create', () => {
+ vm = createTest(Cascader, true);
+ expect(vm.$el).to.exist;
+ });
+});
+