├── examples ├── assets │ ├── styles │ │ ├── common.css │ │ └── fonts │ │ │ ├── icomoon.eot │ │ │ ├── icomoon.ttf │ │ │ ├── icomoon.woff │ │ │ └── style.css │ └── images │ │ ├── web.png │ │ ├── guide.png │ │ ├── cloud-1.png │ │ ├── cloud-2.png │ │ ├── compo-1.png │ │ ├── compo-2.png │ │ ├── compo-3.png │ │ ├── feedback.png │ │ ├── figure-1.png │ │ ├── figure-2.png │ │ ├── navbar_0.png │ │ ├── navbar_1.png │ │ ├── navbar_2.png │ │ ├── navbar_3.png │ │ ├── plant-1.png │ │ ├── plant-2.png │ │ ├── qrcode.png │ │ ├── resource.png │ │ ├── component.png │ │ ├── efficiency.png │ │ ├── hamburger.png │ │ ├── button-d-cn.png │ │ ├── button-d-en.png │ │ ├── button-l-cn.png │ │ ├── button-l-en.png │ │ ├── consistency.png │ │ ├── dialog-close.png │ │ ├── element-demo.jpeg │ │ ├── controllability.png │ │ ├── duotai.svg │ │ └── duohui.svg ├── bus.js ├── favicon.ico ├── versions.json ├── play │ └── index.vue ├── i18n │ ├── route.json │ └── title.json ├── play.js ├── dom │ └── class.js ├── icon.json ├── docs │ ├── zh-CN │ │ ├── installation.md │ │ └── breadcrumb.md │ ├── en-US │ │ └── installation.md │ └── es │ │ └── installation.md ├── entry.js └── index.tpl ├── packages ├── theme-chalk │ ├── src │ │ ├── submenu.scss │ │ ├── tab-pane.scss │ │ ├── button-group.scss │ │ ├── collapse-item.scss │ │ ├── dropdown-item.scss │ │ ├── dropdown-menu.scss │ │ ├── form-item.scss │ │ ├── menu-item.scss │ │ ├── breadcrumb-item.scss │ │ ├── checkbox-button.scss │ │ ├── checkbox-group.scss │ │ ├── menu-item-group.scss │ │ ├── base.scss │ │ ├── fonts │ │ │ ├── element-icons.ttf │ │ │ └── element-icons.woff │ │ ├── mixins │ │ │ ├── config.scss │ │ │ ├── utils.scss │ │ │ └── function.scss │ │ ├── aside.scss │ │ ├── footer.scss │ │ ├── header.scss │ │ ├── radio-group.scss │ │ ├── container.scss │ │ ├── time-picker.scss │ │ ├── display.scss │ │ ├── main.scss │ │ ├── steps.scss │ │ ├── date-picker.scss │ │ ├── common │ │ │ └── popup.scss │ │ ├── date-picker │ │ │ ├── time-range-picker.scss │ │ │ ├── month-table.scss │ │ │ ├── year-table.scss │ │ │ └── time-picker.scss │ │ ├── card.scss │ │ ├── time-select.scss │ │ ├── spinner.scss │ │ ├── row.scss │ │ ├── option-group.scss │ │ ├── option.scss │ │ ├── popover.scss │ │ ├── rate.scss │ │ ├── carousel-item.scss │ │ ├── breadcrumb.scss │ │ ├── scrollbar.scss │ │ ├── reset.scss │ │ ├── badge.scss │ │ ├── select-dropdown.scss │ │ ├── collapse.scss │ │ └── autocomplete.scss │ ├── .gitignore │ ├── README.md │ ├── gulpfile.js │ └── package.json ├── message │ ├── index.js │ └── src │ │ └── main.js ├── message-box │ └── index.js ├── notification │ └── index.js ├── card │ ├── index.js │ └── src │ │ └── main.vue ├── main │ ├── index.js │ └── src │ │ └── main.vue ├── rate │ └── index.js ├── tag │ ├── index.js │ └── src │ │ └── tag.vue ├── tree │ ├── index.js │ └── src │ │ └── model │ │ └── util.js ├── alert │ └── index.js ├── aside │ ├── index.js │ └── src │ │ └── main.vue ├── badge │ ├── index.js │ └── src │ │ └── main.vue ├── form │ └── index.js ├── menu │ ├── index.js │ └── src │ │ ├── menu-item-group.vue │ │ └── menu-mixin.js ├── radio │ └── index.js ├── row │ ├── index.js │ └── src │ │ └── row.js ├── step │ └── index.js ├── steps │ ├── index.js │ ├── src │ │ └── steps.vue │ └── README.md ├── tabs │ ├── index.js │ └── src │ │ ├── tab-pane.vue │ │ └── tab-bar.vue ├── upload │ └── index.js ├── footer │ ├── index.js │ └── src │ │ └── main.vue ├── header │ ├── index.js │ └── src │ │ └── main.vue ├── icon │ ├── index.js │ └── src │ │ └── icon.vue ├── select │ ├── index.js │ └── src │ │ ├── option-group.vue │ │ ├── navigation-mixin.js │ │ └── select-dropdown.vue ├── slider │ └── index.js ├── col │ ├── index.js │ └── src │ │ └── col.js ├── input │ └── index.js ├── table │ ├── index.js │ └── src │ │ └── dropdown.js ├── tooltip │ └── index.js ├── button │ ├── index.js │ └── src │ │ ├── button-group.vue │ │ └── button.vue ├── carousel │ └── index.js ├── cascader │ └── index.js ├── spinner │ ├── index.js │ └── src │ │ └── spinner.vue ├── transfer │ └── index.js ├── container │ ├── index.js │ └── src │ │ └── main.vue ├── dialog │ └── index.js ├── scrollbar │ ├── index.js │ └── src │ │ └── util.js ├── option │ └── index.js ├── switch │ └── index.js ├── tab-pane │ └── index.js ├── checkbox │ ├── index.js │ └── src │ │ └── checkbox-group.vue ├── dropdown │ ├── index.js │ └── src │ │ ├── dropdown-item.vue │ │ └── dropdown-menu.vue ├── progress │ └── index.js ├── submenu │ └── index.js ├── color-picker │ ├── index.js │ └── src │ │ ├── draggable.js │ │ └── components │ │ └── predefine.vue ├── pagination │ └── index.js ├── form-item │ └── index.js ├── menu-item │ └── index.js ├── breadcrumb │ ├── index.js │ └── src │ │ ├── breadcrumb.vue │ │ └── breadcrumb-item.vue ├── collapse │ ├── index.js │ └── src │ │ └── collapse.vue ├── radio-group │ └── index.js ├── date-picker │ ├── index.js │ └── src │ │ └── picker │ │ ├── time-select.js │ │ ├── date-picker.js │ │ └── time-picker.js ├── input-number │ └── index.js ├── radio-button │ └── index.js ├── time-picker │ └── index.js ├── time-select │ └── index.js ├── autocomplete │ └── index.js ├── button-group │ └── index.js ├── carousel-item │ └── index.js ├── option-group │ └── index.js ├── table-column │ └── index.js ├── dropdown-item │ └── index.js ├── dropdown-menu │ └── index.js ├── collapse-item │ └── index.js ├── loading │ ├── index.js │ └── src │ │ └── loading.vue ├── menu-item-group │ └── index.js ├── checkbox-group │ └── index.js ├── breadcrumb-item │ └── index.js ├── checkbox-button │ └── index.js └── popover │ ├── index.js │ └── src │ └── directive.js ├── .gitattributes ├── types ├── index.d.ts ├── main.d.ts ├── button-group.d.ts ├── dropdown-menu.d.ts ├── aside.d.ts ├── footer.d.ts ├── header.d.ts ├── menu-item-group.d.ts ├── container.d.ts ├── menu-item.d.ts ├── option-group.d.ts ├── carousel-item.d.ts ├── collapse.d.ts ├── breadcrumb.d.ts ├── breadcrumb-item.d.ts ├── option.d.ts ├── radio-button.d.ts ├── badge.d.ts ├── dropdown-item.d.ts ├── component.d.ts ├── radio.d.ts ├── radio-group.d.ts ├── tab-pane.d.ts ├── collapse-item.d.ts ├── card.d.ts ├── submenu.d.ts ├── color-picker.d.ts ├── tag.d.ts ├── checkbox-button.d.ts ├── checkbox-group.d.ts ├── alert.d.ts ├── row.d.ts ├── step.d.ts ├── progress.d.ts ├── dropdown.d.ts ├── steps.d.ts ├── checkbox.d.ts ├── tabs.d.ts ├── input-number.d.ts ├── button.d.ts ├── switch.d.ts ├── pagination.d.ts ├── form-item.d.ts ├── col.d.ts ├── tooltip.d.ts ├── time-select.d.ts ├── menu.d.ts ├── carousel.d.ts ├── slider.d.ts ├── rate.d.ts ├── cascader.d.ts ├── time-picker.d.ts ├── dialog.d.ts ├── popover.d.ts └── transfer.d.ts ├── .eslintignore ├── src ├── mixins │ ├── focus.js │ ├── locale.js │ ├── emitter.js │ └── migrating.js ├── utils │ ├── shared.js │ ├── vdom.js │ ├── merge.js │ ├── menu │ │ ├── aria-menubar.js │ │ ├── aria-menuitem.js │ │ └── aria-submenu.js │ ├── scrollbar-width.js │ ├── scroll-into-view.js │ ├── after-leave.js │ └── resize-event.js ├── directives │ ├── mousewheel.js │ └── repeat-click.js └── locale │ ├── format.js │ └── index.js ├── .gitignore ├── .babelrc ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.zh-CN.md ├── .eslintrc ├── postcss.config.js ├── .travis.yml ├── test └── unit │ ├── index.js │ ├── specs │ ├── breadcrumb.spec.js │ ├── badge.spec.js │ ├── row.spec.js │ ├── card.spec.js │ └── alert.spec.js │ └── karma.conf.js ├── LICENSE └── Makefile /examples/assets/styles/common.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/submenu.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/tab-pane.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/button-group.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/collapse-item.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/dropdown-item.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/dropdown-menu.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/form-item.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/menu-item.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/breadcrumb-item.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/checkbox-button.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/checkbox-group.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/menu-item-group.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | test/**/*.js linguist-language=Vue 2 | -------------------------------------------------------------------------------- /examples/bus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | export default new Vue(); 3 | -------------------------------------------------------------------------------- /packages/theme-chalk/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | npm-debug* 4 | -------------------------------------------------------------------------------- /examples/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/favicon.ico -------------------------------------------------------------------------------- /packages/message/index.js: -------------------------------------------------------------------------------- 1 | import Message from './src/main.js'; 2 | export default Message; 3 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/base.scss: -------------------------------------------------------------------------------- 1 | @import "common/transition.scss"; 2 | @import "icon.scss"; 3 | -------------------------------------------------------------------------------- /examples/assets/images/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/web.png -------------------------------------------------------------------------------- /packages/message-box/index.js: -------------------------------------------------------------------------------- 1 | import MessageBox from './src/main.js'; 2 | export default MessageBox; 3 | -------------------------------------------------------------------------------- /examples/assets/images/guide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/guide.png -------------------------------------------------------------------------------- /examples/versions.json: -------------------------------------------------------------------------------- 1 | {"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.9":"2.4"} -------------------------------------------------------------------------------- /packages/notification/index.js: -------------------------------------------------------------------------------- 1 | import Notification from './src/main.js'; 2 | export default Notification; 3 | -------------------------------------------------------------------------------- /examples/assets/images/cloud-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/cloud-1.png -------------------------------------------------------------------------------- /examples/assets/images/cloud-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/cloud-2.png -------------------------------------------------------------------------------- /examples/assets/images/compo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/compo-1.png -------------------------------------------------------------------------------- /examples/assets/images/compo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/compo-2.png -------------------------------------------------------------------------------- /examples/assets/images/compo-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/compo-3.png -------------------------------------------------------------------------------- /examples/assets/images/feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/feedback.png -------------------------------------------------------------------------------- /examples/assets/images/figure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/figure-1.png -------------------------------------------------------------------------------- /examples/assets/images/figure-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/figure-2.png -------------------------------------------------------------------------------- /examples/assets/images/navbar_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/navbar_0.png -------------------------------------------------------------------------------- /examples/assets/images/navbar_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/navbar_1.png -------------------------------------------------------------------------------- /examples/assets/images/navbar_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/navbar_2.png -------------------------------------------------------------------------------- /examples/assets/images/navbar_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/navbar_3.png -------------------------------------------------------------------------------- /examples/assets/images/plant-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/plant-1.png -------------------------------------------------------------------------------- /examples/assets/images/plant-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/plant-2.png -------------------------------------------------------------------------------- /examples/assets/images/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/qrcode.png -------------------------------------------------------------------------------- /examples/assets/images/resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/resource.png -------------------------------------------------------------------------------- /examples/assets/images/component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/component.png -------------------------------------------------------------------------------- /examples/assets/images/efficiency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/efficiency.png -------------------------------------------------------------------------------- /examples/assets/images/hamburger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/hamburger.png -------------------------------------------------------------------------------- /examples/assets/images/button-d-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/button-d-cn.png -------------------------------------------------------------------------------- /examples/assets/images/button-d-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/button-d-en.png -------------------------------------------------------------------------------- /examples/assets/images/button-l-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/button-l-cn.png -------------------------------------------------------------------------------- /examples/assets/images/button-l-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/button-l-en.png -------------------------------------------------------------------------------- /examples/assets/images/consistency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/consistency.png -------------------------------------------------------------------------------- /examples/assets/images/dialog-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/dialog-close.png -------------------------------------------------------------------------------- /examples/assets/images/element-demo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/element-demo.jpeg -------------------------------------------------------------------------------- /examples/assets/styles/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/styles/fonts/icomoon.eot -------------------------------------------------------------------------------- /examples/assets/styles/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/styles/fonts/icomoon.ttf -------------------------------------------------------------------------------- /examples/assets/images/controllability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/images/controllability.png -------------------------------------------------------------------------------- /examples/assets/styles/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/examples/assets/styles/fonts/icomoon.woff -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './element-ui' 2 | 3 | import * as ElementUI from './element-ui' 4 | export default ElementUI 5 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/packages/theme-chalk/src/fonts/element-icons.ttf -------------------------------------------------------------------------------- /packages/theme-chalk/src/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliuq/element/dev/packages/theme-chalk/src/fonts/element-icons.woff -------------------------------------------------------------------------------- /packages/theme-chalk/src/mixins/config.scss: -------------------------------------------------------------------------------- 1 | $namespace: 'el'; 2 | $element-separator: '__'; 3 | $modifier-separator: '--'; 4 | $state-prefix: 'is-'; 5 | -------------------------------------------------------------------------------- /examples/play/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 9 | -------------------------------------------------------------------------------- /types/main.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Main Component */ 4 | export declare class ElMain extends ElementUIComponent {} 5 | -------------------------------------------------------------------------------- /examples/i18n/route.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "lang": "zh-CN" 4 | }, 5 | { 6 | "lang": "en-US" 7 | }, 8 | { 9 | "lang": "es" 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/aside.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | 3 | @include b(aside) { 4 | overflow: auto; 5 | box-sizing: border-box; 6 | flex-shrink: 0; 7 | } 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/utils/popper.js 2 | src/utils/date.js 3 | examples/play 4 | *.sh 5 | node_modules 6 | lib 7 | coverage 8 | *.md 9 | *.scss 10 | *.woff 11 | *.ttf 12 | -------------------------------------------------------------------------------- /types/button-group.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Button Group Component */ 4 | export declare class ElButtonGroup extends ElementUIComponent {} 5 | -------------------------------------------------------------------------------- /types/dropdown-menu.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Dropdown Menu Component */ 4 | export declare class ElDropdownMenu extends ElementUIComponent {} 5 | -------------------------------------------------------------------------------- /src/mixins/focus.js: -------------------------------------------------------------------------------- 1 | export default function(ref) { 2 | return { 3 | methods: { 4 | focus() { 5 | this.$refs[ref].focus(); 6 | } 7 | } 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/card/index.js: -------------------------------------------------------------------------------- 1 | import Card from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Card.install = function(Vue) { 5 | Vue.component(Card.name, Card); 6 | }; 7 | 8 | export default Card; 9 | -------------------------------------------------------------------------------- /packages/main/index.js: -------------------------------------------------------------------------------- 1 | import Main from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Main.install = function(Vue) { 5 | Vue.component(Main.name, Main); 6 | }; 7 | 8 | export default Main; 9 | -------------------------------------------------------------------------------- /packages/rate/index.js: -------------------------------------------------------------------------------- 1 | import Rate from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Rate.install = function(Vue) { 5 | Vue.component(Rate.name, Rate); 6 | }; 7 | 8 | export default Rate; 9 | -------------------------------------------------------------------------------- /packages/tag/index.js: -------------------------------------------------------------------------------- 1 | import ElTag from './src/tag'; 2 | 3 | /* istanbul ignore next */ 4 | ElTag.install = function(Vue) { 5 | Vue.component(ElTag.name, ElTag); 6 | }; 7 | 8 | export default ElTag; 9 | -------------------------------------------------------------------------------- /packages/tree/index.js: -------------------------------------------------------------------------------- 1 | import Tree from './src/tree.vue'; 2 | 3 | /* istanbul ignore next */ 4 | Tree.install = function(Vue) { 5 | Vue.component(Tree.name, Tree); 6 | }; 7 | 8 | export default Tree; 9 | -------------------------------------------------------------------------------- /src/mixins/locale.js: -------------------------------------------------------------------------------- 1 | import { t } from 'element-ui/src/locale'; 2 | 3 | export default { 4 | methods: { 5 | t(...args) { 6 | return t.apply(this, args); 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/alert/index.js: -------------------------------------------------------------------------------- 1 | import Alert from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Alert.install = function(Vue) { 5 | Vue.component(Alert.name, Alert); 6 | }; 7 | 8 | export default Alert; 9 | -------------------------------------------------------------------------------- /packages/aside/index.js: -------------------------------------------------------------------------------- 1 | import Aside from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Aside.install = function(Vue) { 5 | Vue.component(Aside.name, Aside); 6 | }; 7 | 8 | export default Aside; 9 | -------------------------------------------------------------------------------- /packages/badge/index.js: -------------------------------------------------------------------------------- 1 | import Badge from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Badge.install = function(Vue) { 5 | Vue.component(Badge.name, Badge); 6 | }; 7 | 8 | export default Badge; 9 | -------------------------------------------------------------------------------- /packages/form/index.js: -------------------------------------------------------------------------------- 1 | import ElForm from './src/form'; 2 | 3 | /* istanbul ignore next */ 4 | ElForm.install = function(Vue) { 5 | Vue.component(ElForm.name, ElForm); 6 | }; 7 | 8 | export default ElForm; 9 | -------------------------------------------------------------------------------- /packages/menu/index.js: -------------------------------------------------------------------------------- 1 | import ElMenu from './src/menu'; 2 | 3 | /* istanbul ignore next */ 4 | ElMenu.install = function(Vue) { 5 | Vue.component(ElMenu.name, ElMenu); 6 | }; 7 | 8 | export default ElMenu; 9 | -------------------------------------------------------------------------------- /packages/radio/index.js: -------------------------------------------------------------------------------- 1 | import Radio from './src/radio'; 2 | 3 | /* istanbul ignore next */ 4 | Radio.install = function(Vue) { 5 | Vue.component(Radio.name, Radio); 6 | }; 7 | 8 | export default Radio; 9 | -------------------------------------------------------------------------------- /packages/row/index.js: -------------------------------------------------------------------------------- 1 | import Row from './src/row'; 2 | 3 | /* istanbul ignore next */ 4 | Row.install = function(Vue) { 5 | Vue.component(Row.name, Row); 6 | }; 7 | 8 | export default Row; 9 | 10 | -------------------------------------------------------------------------------- /packages/step/index.js: -------------------------------------------------------------------------------- 1 | import Step from '../steps/src/step'; 2 | 3 | /* istanbul ignore next */ 4 | Step.install = function(Vue) { 5 | Vue.component(Step.name, Step); 6 | }; 7 | 8 | export default Step; 9 | -------------------------------------------------------------------------------- /packages/steps/index.js: -------------------------------------------------------------------------------- 1 | import Steps from './src/steps'; 2 | 3 | /* istanbul ignore next */ 4 | Steps.install = function(Vue) { 5 | Vue.component(Steps.name, Steps); 6 | }; 7 | 8 | export default Steps; 9 | -------------------------------------------------------------------------------- /packages/tabs/index.js: -------------------------------------------------------------------------------- 1 | import ElTabs from './src/tabs'; 2 | 3 | /* istanbul ignore next */ 4 | ElTabs.install = function(Vue) { 5 | Vue.component(ElTabs.name, ElTabs); 6 | }; 7 | 8 | export default ElTabs; 9 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/footer.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(footer) { 5 | padding: $--footer-padding; 6 | box-sizing: border-box; 7 | flex-shrink: 0; 8 | } 9 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/header.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(header) { 5 | padding: $--header-padding; 6 | box-sizing: border-box; 7 | flex-shrink: 0; 8 | } 9 | -------------------------------------------------------------------------------- /packages/upload/index.js: -------------------------------------------------------------------------------- 1 | import Upload from './src'; 2 | 3 | /* istanbul ignore next */ 4 | Upload.install = function(Vue) { 5 | Vue.component(Upload.name, Upload); 6 | }; 7 | 8 | export default Upload; 9 | -------------------------------------------------------------------------------- /packages/footer/index.js: -------------------------------------------------------------------------------- 1 | import Footer from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Footer.install = function(Vue) { 5 | Vue.component(Footer.name, Footer); 6 | }; 7 | 8 | export default Footer; 9 | -------------------------------------------------------------------------------- /packages/header/index.js: -------------------------------------------------------------------------------- 1 | import Header from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Header.install = function(Vue) { 5 | Vue.component(Header.name, Header); 6 | }; 7 | 8 | export default Header; 9 | -------------------------------------------------------------------------------- /packages/icon/index.js: -------------------------------------------------------------------------------- 1 | import ElIcon from './src/icon.vue'; 2 | 3 | /* istanbul ignore next */ 4 | ElIcon.install = function(Vue) { 5 | Vue.component(ElIcon.name, ElIcon); 6 | }; 7 | 8 | export default ElIcon; 9 | -------------------------------------------------------------------------------- /packages/select/index.js: -------------------------------------------------------------------------------- 1 | import Select from './src/select'; 2 | 3 | /* istanbul ignore next */ 4 | Select.install = function(Vue) { 5 | Vue.component(Select.name, Select); 6 | }; 7 | 8 | export default Select; 9 | -------------------------------------------------------------------------------- /packages/slider/index.js: -------------------------------------------------------------------------------- 1 | import Slider from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Slider.install = function(Vue) { 5 | Vue.component(Slider.name, Slider); 6 | }; 7 | 8 | export default Slider; 9 | -------------------------------------------------------------------------------- /packages/col/index.js: -------------------------------------------------------------------------------- 1 | import ElCol from './src/col'; 2 | 3 | /* istanbul ignore next */ 4 | ElCol.install = function(Vue) { 5 | Vue.component(ElCol.name, ElCol); 6 | }; 7 | 8 | export default ElCol; 9 | 10 | -------------------------------------------------------------------------------- /packages/input/index.js: -------------------------------------------------------------------------------- 1 | import ElInput from './src/input'; 2 | 3 | /* istanbul ignore next */ 4 | ElInput.install = function(Vue) { 5 | Vue.component(ElInput.name, ElInput); 6 | }; 7 | 8 | export default ElInput; 9 | -------------------------------------------------------------------------------- /packages/table/index.js: -------------------------------------------------------------------------------- 1 | import ElTable from './src/table'; 2 | 3 | /* istanbul ignore next */ 4 | ElTable.install = function(Vue) { 5 | Vue.component(ElTable.name, ElTable); 6 | }; 7 | 8 | export default ElTable; 9 | -------------------------------------------------------------------------------- /packages/tooltip/index.js: -------------------------------------------------------------------------------- 1 | import Tooltip from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Tooltip.install = function(Vue) { 5 | Vue.component(Tooltip.name, Tooltip); 6 | }; 7 | 8 | export default Tooltip; 9 | -------------------------------------------------------------------------------- /packages/button/index.js: -------------------------------------------------------------------------------- 1 | import ElButton from './src/button'; 2 | 3 | /* istanbul ignore next */ 4 | ElButton.install = function(Vue) { 5 | Vue.component(ElButton.name, ElButton); 6 | }; 7 | 8 | export default ElButton; 9 | -------------------------------------------------------------------------------- /packages/carousel/index.js: -------------------------------------------------------------------------------- 1 | import Carousel from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Carousel.install = function(Vue) { 5 | Vue.component(Carousel.name, Carousel); 6 | }; 7 | 8 | export default Carousel; 9 | -------------------------------------------------------------------------------- /packages/cascader/index.js: -------------------------------------------------------------------------------- 1 | import Cascader from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Cascader.install = function(Vue) { 5 | Vue.component(Cascader.name, Cascader); 6 | }; 7 | 8 | export default Cascader; 9 | -------------------------------------------------------------------------------- /packages/spinner/index.js: -------------------------------------------------------------------------------- 1 | import Spinner from './src/spinner'; 2 | 3 | /* istanbul ignore next */ 4 | Spinner.install = function(Vue) { 5 | Vue.component(Spinner.name, Spinner); 6 | }; 7 | 8 | export default Spinner; 9 | -------------------------------------------------------------------------------- /packages/transfer/index.js: -------------------------------------------------------------------------------- 1 | import Transfer from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Transfer.install = function(Vue) { 5 | Vue.component(Transfer.name, Transfer); 6 | }; 7 | 8 | export default Transfer; 9 | -------------------------------------------------------------------------------- /types/aside.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Aside Component */ 4 | export declare class ElAside extends ElementUIComponent { 5 | /** Width of the side section */ 6 | width: string 7 | } 8 | -------------------------------------------------------------------------------- /types/footer.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Footer Component */ 4 | export declare class ElFooter extends ElementUIComponent { 5 | /** Height of the footer */ 6 | height: string 7 | } 8 | -------------------------------------------------------------------------------- /types/header.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Header Component */ 4 | export declare class ElHeader extends ElementUIComponent { 5 | /** Height of the header */ 6 | height: string 7 | } 8 | -------------------------------------------------------------------------------- /packages/container/index.js: -------------------------------------------------------------------------------- 1 | import Container from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Container.install = function(Vue) { 5 | Vue.component(Container.name, Container); 6 | }; 7 | 8 | export default Container; 9 | -------------------------------------------------------------------------------- /packages/dialog/index.js: -------------------------------------------------------------------------------- 1 | import ElDialog from './src/component'; 2 | 3 | /* istanbul ignore next */ 4 | ElDialog.install = function(Vue) { 5 | Vue.component(ElDialog.name, ElDialog); 6 | }; 7 | 8 | export default ElDialog; 9 | -------------------------------------------------------------------------------- /packages/scrollbar/index.js: -------------------------------------------------------------------------------- 1 | import Scrollbar from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | Scrollbar.install = function(Vue) { 5 | Vue.component(Scrollbar.name, Scrollbar); 6 | }; 7 | 8 | export default Scrollbar; 9 | -------------------------------------------------------------------------------- /packages/button/src/button-group.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /packages/option/index.js: -------------------------------------------------------------------------------- 1 | import ElOption from '../select/src/option'; 2 | 3 | /* istanbul ignore next */ 4 | ElOption.install = function(Vue) { 5 | Vue.component(ElOption.name, ElOption); 6 | }; 7 | 8 | export default ElOption; 9 | -------------------------------------------------------------------------------- /packages/switch/index.js: -------------------------------------------------------------------------------- 1 | import Switch from './src/component'; 2 | 3 | /* istanbul ignore next */ 4 | Switch.install = function(Vue) { 5 | Vue.component(Switch.name, Switch); 6 | }; 7 | 8 | export default Switch; 9 | 10 | -------------------------------------------------------------------------------- /packages/tab-pane/index.js: -------------------------------------------------------------------------------- 1 | import TabPane from '../tabs/src/tab-pane.vue'; 2 | 3 | /* istanbul ignore next */ 4 | TabPane.install = function(Vue) { 5 | Vue.component(TabPane.name, TabPane); 6 | }; 7 | 8 | export default TabPane; 9 | -------------------------------------------------------------------------------- /src/utils/shared.js: -------------------------------------------------------------------------------- 1 | export function isDef(val) { 2 | return val !== undefined && val !== null; 3 | } 4 | export function isKorean(text) { 5 | const reg = /([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi; 6 | return reg.test(text); 7 | } 8 | -------------------------------------------------------------------------------- /packages/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import ElCheckbox from './src/checkbox'; 2 | 3 | /* istanbul ignore next */ 4 | ElCheckbox.install = function(Vue) { 5 | Vue.component(ElCheckbox.name, ElCheckbox); 6 | }; 7 | 8 | export default ElCheckbox; 9 | -------------------------------------------------------------------------------- /packages/dropdown/index.js: -------------------------------------------------------------------------------- 1 | import ElDropdown from './src/dropdown'; 2 | 3 | /* istanbul ignore next */ 4 | ElDropdown.install = function(Vue) { 5 | Vue.component(ElDropdown.name, ElDropdown); 6 | }; 7 | 8 | export default ElDropdown; 9 | -------------------------------------------------------------------------------- /packages/progress/index.js: -------------------------------------------------------------------------------- 1 | import ElProgress from './src/progress'; 2 | 3 | /* istanbul ignore next */ 4 | ElProgress.install = function(Vue) { 5 | Vue.component(ElProgress.name, ElProgress); 6 | }; 7 | 8 | export default ElProgress; 9 | -------------------------------------------------------------------------------- /packages/submenu/index.js: -------------------------------------------------------------------------------- 1 | import ElSubmenu from '../menu/src/submenu'; 2 | 3 | /* istanbul ignore next */ 4 | ElSubmenu.install = function(Vue) { 5 | Vue.component(ElSubmenu.name, ElSubmenu); 6 | }; 7 | 8 | export default ElSubmenu; 9 | -------------------------------------------------------------------------------- /types/menu-item-group.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Menu Item Group Component */ 4 | export declare class ElMenuItemGroup extends ElementUIComponent { 5 | /** Group title */ 6 | title: string 7 | } 8 | -------------------------------------------------------------------------------- /packages/color-picker/index.js: -------------------------------------------------------------------------------- 1 | import ColorPicker from './src/main'; 2 | 3 | /* istanbul ignore next */ 4 | ColorPicker.install = function(Vue) { 5 | Vue.component(ColorPicker.name, ColorPicker); 6 | }; 7 | 8 | export default ColorPicker; 9 | -------------------------------------------------------------------------------- /packages/pagination/index.js: -------------------------------------------------------------------------------- 1 | import Pagination from './src/pagination'; 2 | 3 | /* istanbul ignore next */ 4 | Pagination.install = function(Vue) { 5 | Vue.component(Pagination.name, Pagination); 6 | }; 7 | 8 | export default Pagination; 9 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/radio-group.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(radio-group) { 5 | display: inline-block; 6 | line-height: 1; 7 | vertical-align: middle; 8 | font-size: 0; 9 | } 10 | -------------------------------------------------------------------------------- /packages/form-item/index.js: -------------------------------------------------------------------------------- 1 | import ElFormItem from '../form/src/form-item'; 2 | 3 | /* istanbul ignore next */ 4 | ElFormItem.install = function(Vue) { 5 | Vue.component(ElFormItem.name, ElFormItem); 6 | }; 7 | 8 | export default ElFormItem; 9 | -------------------------------------------------------------------------------- /packages/menu-item/index.js: -------------------------------------------------------------------------------- 1 | import ElMenuItem from '../menu/src/menu-item'; 2 | 3 | /* istanbul ignore next */ 4 | ElMenuItem.install = function(Vue) { 5 | Vue.component(ElMenuItem.name, ElMenuItem); 6 | }; 7 | 8 | export default ElMenuItem; 9 | -------------------------------------------------------------------------------- /packages/breadcrumb/index.js: -------------------------------------------------------------------------------- 1 | import ElBreadcrumb from './src/breadcrumb'; 2 | 3 | /* istanbul ignore next */ 4 | ElBreadcrumb.install = function(Vue) { 5 | Vue.component(ElBreadcrumb.name, ElBreadcrumb); 6 | }; 7 | 8 | export default ElBreadcrumb; 9 | -------------------------------------------------------------------------------- /packages/collapse/index.js: -------------------------------------------------------------------------------- 1 | import ElCollapse from './src/collapse'; 2 | 3 | /* istanbul ignore next */ 4 | ElCollapse.install = function(Vue) { 5 | Vue.component(ElCollapse.name, ElCollapse); 6 | }; 7 | 8 | export default ElCollapse; 9 | 10 | -------------------------------------------------------------------------------- /packages/icon/src/icon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | -------------------------------------------------------------------------------- /packages/main/src/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /packages/radio-group/index.js: -------------------------------------------------------------------------------- 1 | import RadioGroup from '../radio/src/radio-group.vue'; 2 | 3 | /* istanbul ignore next */ 4 | RadioGroup.install = function(Vue) { 5 | Vue.component(RadioGroup.name, RadioGroup); 6 | }; 7 | 8 | export default RadioGroup; 9 | -------------------------------------------------------------------------------- /packages/date-picker/index.js: -------------------------------------------------------------------------------- 1 | import DatePicker from './src/picker/date-picker'; 2 | 3 | /* istanbul ignore next */ 4 | DatePicker.install = function install(Vue) { 5 | Vue.component(DatePicker.name, DatePicker); 6 | }; 7 | 8 | export default DatePicker; 9 | -------------------------------------------------------------------------------- /packages/input-number/index.js: -------------------------------------------------------------------------------- 1 | import ElInputNumber from './src/input-number'; 2 | 3 | /* istanbul ignore next */ 4 | ElInputNumber.install = function(Vue) { 5 | Vue.component(ElInputNumber.name, ElInputNumber); 6 | }; 7 | 8 | export default ElInputNumber; 9 | -------------------------------------------------------------------------------- /packages/radio-button/index.js: -------------------------------------------------------------------------------- 1 | import RadioButton from '../radio/src/radio-button.vue'; 2 | 3 | /* istanbul ignore next */ 4 | RadioButton.install = function(Vue) { 5 | Vue.component(RadioButton.name, RadioButton); 6 | }; 7 | 8 | export default RadioButton; 9 | -------------------------------------------------------------------------------- /packages/time-picker/index.js: -------------------------------------------------------------------------------- 1 | import TimePicker from '../date-picker/src/picker/time-picker'; 2 | 3 | /* istanbul ignore next */ 4 | TimePicker.install = function(Vue) { 5 | Vue.component(TimePicker.name, TimePicker); 6 | }; 7 | 8 | export default TimePicker; 9 | -------------------------------------------------------------------------------- /packages/time-select/index.js: -------------------------------------------------------------------------------- 1 | import TimeSelect from '../date-picker/src/picker/time-select'; 2 | 3 | /* istanbul ignore next */ 4 | TimeSelect.install = function(Vue) { 5 | Vue.component(TimeSelect.name, TimeSelect); 6 | }; 7 | 8 | export default TimeSelect; 9 | -------------------------------------------------------------------------------- /packages/autocomplete/index.js: -------------------------------------------------------------------------------- 1 | import ElAutocomplete from './src/autocomplete'; 2 | 3 | /* istanbul ignore next */ 4 | ElAutocomplete.install = function(Vue) { 5 | Vue.component(ElAutocomplete.name, ElAutocomplete); 6 | }; 7 | 8 | export default ElAutocomplete; 9 | -------------------------------------------------------------------------------- /packages/button-group/index.js: -------------------------------------------------------------------------------- 1 | import ElButtonGroup from '../button/src/button-group'; 2 | 3 | /* istanbul ignore next */ 4 | ElButtonGroup.install = function(Vue) { 5 | Vue.component(ElButtonGroup.name, ElButtonGroup); 6 | }; 7 | 8 | export default ElButtonGroup; 9 | -------------------------------------------------------------------------------- /packages/carousel-item/index.js: -------------------------------------------------------------------------------- 1 | import ElCarouselItem from '../carousel/src/item'; 2 | 3 | /* istanbul ignore next */ 4 | ElCarouselItem.install = function(Vue) { 5 | Vue.component(ElCarouselItem.name, ElCarouselItem); 6 | }; 7 | 8 | export default ElCarouselItem; 9 | -------------------------------------------------------------------------------- /packages/option-group/index.js: -------------------------------------------------------------------------------- 1 | import ElOptionGroup from '../select/src/option-group'; 2 | 3 | /* istanbul ignore next */ 4 | ElOptionGroup.install = function(Vue) { 5 | Vue.component(ElOptionGroup.name, ElOptionGroup); 6 | }; 7 | 8 | export default ElOptionGroup; 9 | -------------------------------------------------------------------------------- /packages/table-column/index.js: -------------------------------------------------------------------------------- 1 | import ElTableColumn from '../table/src/table-column'; 2 | 3 | /* istanbul ignore next */ 4 | ElTableColumn.install = function(Vue) { 5 | Vue.component(ElTableColumn.name, ElTableColumn); 6 | }; 7 | 8 | export default ElTableColumn; 9 | -------------------------------------------------------------------------------- /types/container.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Container Component */ 4 | export declare class ElContainer extends ElementUIComponent { 5 | /** Layout direction for child elements */ 6 | direction: 'horizontal' | 'vertical' 7 | } 8 | -------------------------------------------------------------------------------- /packages/dropdown-item/index.js: -------------------------------------------------------------------------------- 1 | import ElDropdownItem from '../dropdown/src/dropdown-item'; 2 | 3 | /* istanbul ignore next */ 4 | ElDropdownItem.install = function(Vue) { 5 | Vue.component(ElDropdownItem.name, ElDropdownItem); 6 | }; 7 | 8 | export default ElDropdownItem; 9 | -------------------------------------------------------------------------------- /packages/dropdown-menu/index.js: -------------------------------------------------------------------------------- 1 | import ElDropdownMenu from '../dropdown/src/dropdown-menu'; 2 | 3 | /* istanbul ignore next */ 4 | ElDropdownMenu.install = function(Vue) { 5 | Vue.component(ElDropdownMenu.name, ElDropdownMenu); 6 | }; 7 | 8 | export default ElDropdownMenu; 9 | -------------------------------------------------------------------------------- /packages/collapse-item/index.js: -------------------------------------------------------------------------------- 1 | import ElCollapseItem from '../collapse/src/collapse-item.vue'; 2 | 3 | /* istanbul ignore next */ 4 | ElCollapseItem.install = function(Vue) { 5 | Vue.component(ElCollapseItem.name, ElCollapseItem); 6 | }; 7 | 8 | export default ElCollapseItem; 9 | -------------------------------------------------------------------------------- /packages/loading/index.js: -------------------------------------------------------------------------------- 1 | import directive from './src/directive'; 2 | import service from './src/index'; 3 | 4 | export default { 5 | install(Vue) { 6 | Vue.use(directive); 7 | Vue.prototype.$loading = service; 8 | }, 9 | directive, 10 | service 11 | }; 12 | -------------------------------------------------------------------------------- /packages/menu-item-group/index.js: -------------------------------------------------------------------------------- 1 | import ElMenuItemGroup from '../menu/src/menu-item-group'; 2 | 3 | /* istanbul ignore next */ 4 | ElMenuItemGroup.install = function(Vue) { 5 | Vue.component(ElMenuItemGroup.name, ElMenuItemGroup); 6 | }; 7 | 8 | export default ElMenuItemGroup; 9 | -------------------------------------------------------------------------------- /packages/checkbox-group/index.js: -------------------------------------------------------------------------------- 1 | import ElCheckboxGroup from '../checkbox/src/checkbox-group.vue'; 2 | 3 | /* istanbul ignore next */ 4 | ElCheckboxGroup.install = function(Vue) { 5 | Vue.component(ElCheckboxGroup.name, ElCheckboxGroup); 6 | }; 7 | 8 | export default ElCheckboxGroup; 9 | -------------------------------------------------------------------------------- /packages/breadcrumb-item/index.js: -------------------------------------------------------------------------------- 1 | import ElBreadcrumbItem from '../breadcrumb/src/breadcrumb-item'; 2 | 3 | /* istanbul ignore next */ 4 | ElBreadcrumbItem.install = function(Vue) { 5 | Vue.component(ElBreadcrumbItem.name, ElBreadcrumbItem); 6 | }; 7 | 8 | export default ElBreadcrumbItem; 9 | -------------------------------------------------------------------------------- /examples/play.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Element from 'main/index.js'; 3 | import App from './play/index.vue'; 4 | import 'packages/theme-chalk/src/index.scss'; 5 | 6 | Vue.use(Element); 7 | 8 | new Vue({ // eslint-disable-line 9 | render: h => h(App) 10 | }).$mount('#app'); 11 | -------------------------------------------------------------------------------- /packages/checkbox-button/index.js: -------------------------------------------------------------------------------- 1 | import ElCheckboxButton from '../checkbox/src/checkbox-button.vue'; 2 | 3 | /* istanbul ignore next */ 4 | ElCheckboxButton.install = function(Vue) { 5 | Vue.component(ElCheckboxButton.name, ElCheckboxButton); 6 | }; 7 | 8 | export default ElCheckboxButton; 9 | -------------------------------------------------------------------------------- /types/menu-item.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Menu Item Component */ 4 | export declare class ElMenuItem extends ElementUIComponent { 5 | /** Unique identification */ 6 | index: string 7 | 8 | /** Vue Router object */ 9 | route: object 10 | } 11 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/container.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | 3 | @include b(container) { 4 | display: flex; 5 | flex-direction: row; 6 | flex: 1; 7 | flex-basis: auto; 8 | box-sizing: border-box; 9 | min-width: 0; 10 | 11 | @include when(vertical) { 12 | flex-direction: column; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/vdom.js: -------------------------------------------------------------------------------- 1 | import { hasOwn } from 'element-ui/src/utils/util'; 2 | 3 | export function isVNode(node) { 4 | return node !== null && typeof node === 'object' && hasOwn(node, 'componentOptions'); 5 | }; 6 | 7 | export function getFirstComponentChild(children) { 8 | return children && children.filter(c => c && c.tag)[0]; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/time-picker.scss: -------------------------------------------------------------------------------- 1 | @import "./date-picker/picker.scss"; 2 | @import "./date-picker/picker-panel.scss"; 3 | @import "./date-picker/time-spinner.scss"; 4 | @import "./date-picker/time-picker.scss"; 5 | @import "./date-picker/time-range-picker.scss"; 6 | @import "./input.scss"; 7 | @import "./scrollbar.scss"; 8 | @import "./popper"; 9 | -------------------------------------------------------------------------------- /types/option-group.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Dropdown Select Option Group Component */ 4 | export declare class ElOptionGroup extends ElementUIComponent { 5 | /** Name of the group */ 6 | label: string 7 | 8 | /** Whether to disable all options in this group */ 9 | disabled: boolean 10 | } 11 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/display.scss: -------------------------------------------------------------------------------- 1 | @import "common/var"; 2 | @import "mixins/mixins"; 3 | 4 | .hidden { 5 | @each $break-point-name, $value in $--breakpoints-spec { 6 | &-#{$break-point-name} { 7 | @include res($break-point-name, $--breakpoints-spec) { 8 | display: none !important; 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/main.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(main) { 5 | // IE11 supports the
element partially https://caniuse.com/#search=main 6 | display: block; 7 | flex: 1; 8 | flex-basis: auto; 9 | overflow: auto; 10 | box-sizing: border-box; 11 | padding: $--main-padding; 12 | } 13 | -------------------------------------------------------------------------------- /types/carousel-item.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Carousel Item Component */ 4 | export declare class ElCarouselItem extends ElementUIComponent { 5 | /** Name of the item, can be used in setActiveItem */ 6 | name: string 7 | 8 | /** Text content for the corresponding indicator */ 9 | label: string 10 | } 11 | -------------------------------------------------------------------------------- /types/collapse.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Use Collapse to store contents. */ 4 | export declare class ElCollapse extends ElementUIComponent { 5 | /** Whether to activate accordion mode */ 6 | accordion: boolean 7 | 8 | /** Currently active panel */ 9 | value: string | number | string[] | number[] 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | npm-debug.log 4 | lerna-debug.log 5 | npm-debug.log.* 6 | lerna-debug.log.* 7 | lib 8 | .idea 9 | .vscode 10 | examples/element-ui 11 | examples/pages/en-US 12 | examples/pages/zh-CN 13 | examples/pages/es 14 | fe.element/element-ui 15 | .npmrc 16 | coverage 17 | waiter.config.js 18 | build/bin/algolia-key.js 19 | .envrc 20 | -------------------------------------------------------------------------------- /types/breadcrumb.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Displays the location of the current page, making it easier to browser back */ 4 | export declare class ElBreadcrumb extends ElementUIComponent { 5 | /** Separator character */ 6 | separator: string 7 | 8 | /** Class name of the icon separator */ 9 | separatorClass: string 10 | } 11 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["es2015", { "loose": true }]], 3 | "plugins": ["transform-vue-jsx"], 4 | "env": { 5 | "utils": { 6 | "plugins": [ 7 | ["module-resolver", { 8 | "root": ["element-ui"], 9 | "alias": { 10 | "element-ui/src": "element-ui/lib" 11 | } 12 | }] 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /types/breadcrumb-item.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Breadcrumb Item Component */ 4 | export declare class ElBreadcrumbItem extends ElementUIComponent { 5 | /** Target route of the link, same as to of vue-router */ 6 | to: string | object 7 | 8 | /** If true, the navigation will not leave a history record */ 9 | replace: boolean 10 | } 11 | -------------------------------------------------------------------------------- /types/option.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Dropdown Select Option Component */ 4 | export declare class ElOption extends ElementUIComponent { 5 | /** Value of option */ 6 | value: any 7 | 8 | /** Label of option, same as value if omitted */ 9 | label: string 10 | 11 | /** Whether option is disabled */ 12 | disabled: boolean 13 | } 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /packages/aside/src/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /packages/footer/src/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /packages/header/src/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /packages/popover/index.js: -------------------------------------------------------------------------------- 1 | import Popover from './src/main'; 2 | import directive from './src/directive'; 3 | import Vue from 'vue'; 4 | 5 | Vue.directive('popover', directive); 6 | 7 | /* istanbul ignore next */ 8 | Popover.install = function(Vue) { 9 | Vue.directive('popover', directive); 10 | Vue.component(Popover.name, Popover); 11 | }; 12 | Popover.directive = directive; 13 | 14 | export default Popover; 15 | -------------------------------------------------------------------------------- /src/utils/merge.js: -------------------------------------------------------------------------------- 1 | export default function(target) { 2 | for (let i = 1, j = arguments.length; i < j; i++) { 3 | let source = arguments[i] || {}; 4 | for (let prop in source) { 5 | if (source.hasOwnProperty(prop)) { 6 | let value = source[prop]; 7 | if (value !== undefined) { 8 | target[prop] = value; 9 | } 10 | } 11 | } 12 | } 13 | 14 | return target; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/steps.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | 3 | @include b(steps) { 4 | display: flex; 5 | 6 | @include m(simple) { 7 | padding: 13px 8%; 8 | border-radius: 4px; 9 | background: $--background-color-base; 10 | } 11 | 12 | @include m(horizontal) { 13 | white-space: nowrap; 14 | } 15 | 16 | @include m(vertical) { 17 | height: 100%; 18 | flex-flow: column; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | }, 9 | "plugins": ["html", "json"], 10 | "extends": "elemefe", 11 | "rules": { 12 | "no-restricted-globals": ["error", "event", "fdescribe"] 13 | }, 14 | "parserOptions": { 15 | "ecmaFeatures": { 16 | "experimentalObjectRestSpread": true, 17 | "jsx": true 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/date-picker/src/picker/time-select.js: -------------------------------------------------------------------------------- 1 | import Picker from '../picker'; 2 | import Panel from '../panel/time-select'; 3 | 4 | export default { 5 | mixins: [Picker], 6 | 7 | name: 'ElTimeSelect', 8 | 9 | componentName: 'ElTimeSelect', 10 | 11 | props: { 12 | type: { 13 | type: String, 14 | default: 'time-select' 15 | } 16 | }, 17 | 18 | beforeCreate() { 19 | this.panel = Panel; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /types/radio-button.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Radio Button Component */ 4 | export declare class ElRadioButton extends ElementUIComponent { 5 | /** The form input value */ 6 | value: string 7 | 8 | /** The value of radio */ 9 | label: string | number 10 | 11 | /** Whether radio is disabled */ 12 | disabled: boolean 13 | 14 | /** Native 'name' attribute */ 15 | name: string 16 | } 17 | -------------------------------------------------------------------------------- /src/utils/menu/aria-menubar.js: -------------------------------------------------------------------------------- 1 | import MenuItem from './aria-menuitem'; 2 | 3 | const Menu = function(domNode) { 4 | this.domNode = domNode; 5 | this.init(); 6 | }; 7 | 8 | Menu.prototype.init = function() { 9 | let menuChildren = this.domNode.childNodes; 10 | [].filter.call(menuChildren, child => child.nodeType === 1).forEach(child => { 11 | new MenuItem(child); // eslint-disable-line 12 | }); 13 | }; 14 | export default Menu; 15 | -------------------------------------------------------------------------------- /types/badge.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Badge Component */ 4 | export declare class ElBadge extends ElementUIComponent { 5 | /** Display value */ 6 | value: string | number 7 | 8 | /** Maximum value, shows '{max}+' when exceeded. Only works if `value` is a number */ 9 | max: number 10 | 11 | /** If a little dot is displayed */ 12 | isDot: boolean 13 | 14 | /** Hidden badge */ 15 | hidden: boolean 16 | } 17 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-salad': { 4 | browsers: ['ie > 8', 'last 2 versions'], 5 | features: { 6 | bem: { 7 | shortcuts: { 8 | component: 'b', 9 | modifier: 'm', 10 | descendent: 'e' 11 | }, 12 | separators: { 13 | descendent: '__', 14 | modifier: '--' 15 | } 16 | } 17 | } 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /types/dropdown-item.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Toggleable menu for displaying lists of links and actions. */ 4 | export declare class ElDropdownItem extends ElementUIComponent { 5 | /** A command to be dispatched to Dropdown's command callback */ 6 | command: string | number | object 7 | 8 | /** Whether the item is disabled */ 9 | disabled: boolean 10 | 11 | /** Whether a divider is displayed */ 12 | divided: boolean 13 | } 14 | -------------------------------------------------------------------------------- /types/component.d.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | /** ElementUI component common definition */ 4 | export declare class ElementUIComponent extends Vue { 5 | /** Install component into Vue */ 6 | static install (vue: typeof Vue): void 7 | } 8 | 9 | /** Component size definition for button, input, etc */ 10 | export type ElementUIComponentSize = 'large' | 'medium' | 'small' | 'mini' 11 | 12 | /** Horizontal alignment */ 13 | export type ElementUIHorizontalAlignment = 'left' | 'center' | 'right' 14 | -------------------------------------------------------------------------------- /types/radio.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Radio Component */ 4 | export declare class ElRadio extends ElementUIComponent { 5 | /** The form input value */ 6 | value: string 7 | 8 | /** The value of radio */ 9 | label: string | number | boolean 10 | 11 | /** Whether radio is disabled */ 12 | disabled: boolean 13 | 14 | /** Whether to add a border around Radio */ 15 | border: boolean 16 | 17 | /** Native 'name' attribute */ 18 | name: string 19 | } 20 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/date-picker.scss: -------------------------------------------------------------------------------- 1 | @import "./date-picker/date-table.scss"; 2 | @import "./date-picker/month-table.scss"; 3 | @import "./date-picker/year-table.scss"; 4 | @import "./date-picker/time-spinner.scss"; 5 | @import "./date-picker/picker.scss"; 6 | @import "./date-picker/date-picker.scss"; 7 | @import "./date-picker/date-range-picker.scss"; 8 | @import "./date-picker/time-range-picker.scss"; 9 | @import "./date-picker/time-picker.scss"; 10 | @import "./input.scss"; 11 | @import "./scrollbar.scss"; 12 | @import "./popper"; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 8 4 | before_install: 5 | - export CHROME_BIN=chromium-browser 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | - export TRAVIS_COMMIT_MSG="[deploy] $(git log --format='%h - %B' --no-merges -n 1)" 9 | - export TRAVIS_COMMIT_USER="$(git log --no-merges -n 1 --format=%an)" 10 | - export TRAVIS_COMMIT_EMAIL="$(git log --no-merges -n 1 --format=%ae)" 11 | after_success: 12 | - sh build/deploy-ci.sh 13 | - cat ./test/unit/coverage/lcov.info | ./node_modules/.bin/coveralls 14 | -------------------------------------------------------------------------------- /types/radio-group.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type RadioGroupSize = 'large' | 'small' 4 | 5 | /** Radio Group Component */ 6 | export declare class ElRadioGroup extends ElementUIComponent { 7 | /** The size of radio buttons */ 8 | size: RadioGroupSize 9 | 10 | /** Border and background color when button is active */ 11 | fill: string 12 | 13 | /** Whether the nesting radios are disabled */ 14 | disabled: boolean 15 | 16 | /** Font color when button is active */ 17 | textColor: string 18 | } 19 | -------------------------------------------------------------------------------- /types/tab-pane.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Tab Pane Component */ 4 | export declare class ElTabPane extends ElementUIComponent { 5 | /** Title of the tab */ 6 | label: string 7 | 8 | /** Whether Tab is disabled */ 9 | disabled: boolean 10 | 11 | /** Identifier corresponding to the activeName of Tabs, representing the alias of the tab-pane */ 12 | name: string 13 | 14 | /** Whether Tab is closable */ 15 | closable: boolean 16 | 17 | /** Whether Tab is lazily rendered */ 18 | lazy: boolean 19 | } 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please make sure these boxes are checked before submitting your PR, thank you! 2 | 3 | * [ ] Make sure you follow Element's contributing guide ([中文](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.zh-CN.md) | [English](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.en-US.md) | [Español](https://github.com/ElemeFE/element/blob/master/.github/CONTRIBUTING.es.md)). 4 | * [ ] Make sure you are merging your commits to `dev` branch. 5 | * [ ] Add some descriptions and refer relative issues for you PR. 6 | -------------------------------------------------------------------------------- /packages/popover/src/directive.js: -------------------------------------------------------------------------------- 1 | const getReference = (el, binding, vnode) => { 2 | const _ref = binding.expression ? binding.value : binding.arg; 3 | const popper = vnode.context.$refs[_ref]; 4 | if (popper) { 5 | if (Array.isArray(popper)) { 6 | popper[0].$refs.reference = el; 7 | } else { 8 | popper.$refs.reference = el; 9 | } 10 | } 11 | }; 12 | 13 | export default { 14 | bind(el, binding, vnode) { 15 | getReference(el, binding, vnode); 16 | }, 17 | inserted(el, binding, vnode) { 18 | getReference(el, binding, vnode); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /packages/card/src/main.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /types/collapse-item.d.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export interface CollapseItemSlots { 5 | /** Content of the collapse item */ 6 | default: VNode[], 7 | 8 | /** Title of the collapse item */ 9 | title: VNode[] 10 | 11 | [key: string]: VNode[] 12 | } 13 | 14 | /** Collapse Item Component */ 15 | export declare class ElCollapseItem extends ElementUIComponent { 16 | /** Unique identification of the panel */ 17 | name: string | number 18 | 19 | /** Title of the panel */ 20 | title: string 21 | 22 | $slots: CollapseItemSlots 23 | } 24 | -------------------------------------------------------------------------------- /examples/i18n/title.json: -------------------------------------------------------------------------------- 1 | { 2 | "zh-CN": { 3 | "home": "Element - 网站快速成型工具", 4 | "guide": "指南 | Element", 5 | "component": "组件 | Element", 6 | "resource": "资源 | Element" 7 | }, 8 | "en-US": { 9 | "home": "Element - A Desktop UI Toolkit for Web", 10 | "guide": "Guide | Element", 11 | "component": "Component | Element", 12 | "resource": "Resource | Element" 13 | }, 14 | "es": { 15 | "home": "Element - Un kit de interfaz de usuario para la web", 16 | "guide": "Guía | Element", 17 | "component": "Componentes | Element", 18 | "resource": "Recursos | Element" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /types/card.d.ts: -------------------------------------------------------------------------------- 1 | import { VNode, VNodeDirective } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export interface CardSlots { 5 | /** Content of the card */ 6 | default: VNode[], 7 | 8 | /** Title of the card */ 9 | header: VNode[] 10 | 11 | [key: string]: VNode[] 12 | } 13 | 14 | /** Integrate information in a card container */ 15 | export declare class ElCard extends ElementUIComponent { 16 | /** Title of the card */ 17 | header: string 18 | 19 | /** CSS style of body */ 20 | bodyStyle: object 21 | 22 | /** When to show card shadows */ 23 | shadow: string 24 | 25 | $slots: CardSlots 26 | } 27 | -------------------------------------------------------------------------------- /types/submenu.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Submenu Component */ 4 | export declare class ElSubmenu extends ElementUIComponent { 5 | /** Unique identification */ 6 | index: string 7 | 8 | /** Delay time before showing a sub-menu */ 9 | showTimeout: number 10 | 11 | /** Delay time before hiding a sub-menu */ 12 | hideTimeout: number 13 | 14 | /** Custom class name for the popup menu */ 15 | popperClass: string 16 | 17 | /** Whether the sub-menu is disabled */ 18 | disabled: boolean 19 | 20 | /** Whether to append the popper menu to body */ 21 | popperAppendToBody: boolean 22 | } 23 | -------------------------------------------------------------------------------- /src/directives/mousewheel.js: -------------------------------------------------------------------------------- 1 | import normalizeWheel from 'normalize-wheel'; 2 | 3 | const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1; 4 | 5 | const mousewheel = function(element, callback) { 6 | if (element && element.addEventListener) { 7 | element.addEventListener(isFirefox ? 'DOMMouseScroll' : 'mousewheel', function(event) { 8 | const normalized = normalizeWheel(event); 9 | callback && callback.apply(this, [event, normalized]); 10 | }); 11 | } 12 | }; 13 | 14 | export default { 15 | bind(el, binding) { 16 | mousewheel(el, binding.value); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /packages/theme-chalk/README.md: -------------------------------------------------------------------------------- 1 | # element-theme-chalk 2 | > element component chalk theme. 3 | 4 | 5 | ## Installation 6 | ```shell 7 | npm i element-theme-chalk -S 8 | ``` 9 | 10 | ## Usage 11 | 12 | Use Sass import 13 | ```css 14 | @import 'element-theme-chalk'; 15 | ``` 16 | 17 | Or Use webpack 18 | ```javascript 19 | import 'element-theme-chalk'; 20 | ``` 21 | 22 | Or 23 | ```html 24 | 25 | ``` 26 | 27 | ## Import on demand 28 | ```javascript 29 | import 'element-theme-chalk/lib/input.css'; 30 | import 'element-theme-chalk/lib/select.css'; 31 | 32 | // ... 33 | ``` 34 | -------------------------------------------------------------------------------- /examples/dom/class.js: -------------------------------------------------------------------------------- 1 | export const hasClass = function(obj, cls) { 2 | return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); 3 | }; 4 | 5 | export const addClass = function(obj, cls) { 6 | if (!hasClass(obj, cls)) obj.className += ' ' + cls; 7 | }; 8 | 9 | export const removeClass = function(obj, cls) { 10 | if (hasClass(obj, cls)) { 11 | const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); 12 | obj.className = obj.className.replace(reg, ' '); 13 | } 14 | }; 15 | 16 | export const toggleClass = function(obj, cls) { 17 | if (hasClass(obj, cls)) { 18 | removeClass(obj, cls); 19 | } else { 20 | addClass(obj, cls); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind'); 4 | require('packages/theme-chalk/lib/index.css'); 5 | 6 | // require all test files (files that ends with .spec.js) 7 | const testsContext = require.context('./specs', true, /\.spec$/); 8 | testsContext.keys().forEach(testsContext); 9 | 10 | // require all src files except main.js for coverage. 11 | // you can also change this to match only the subset of files that 12 | // you want coverage for. 13 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/); 14 | srcContext.keys().forEach(srcContext); 15 | -------------------------------------------------------------------------------- /types/color-picker.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | export type ColorFormat = 'hsl' | 'hsv' | 'hex' | 'rgb' 4 | 5 | /** ColorPicker Component */ 6 | export declare class ElColorPicker extends ElementUIComponent { 7 | /** Whether to display the alpha slider */ 8 | showAlpha: boolean 9 | 10 | /** Whether to disable the ColorPicker */ 11 | disabled: boolean 12 | 13 | /** Size of ColorPicker */ 14 | size: ElementUIComponentSize 15 | 16 | /** Whether to display the alpha slider */ 17 | popperClass: string 18 | 19 | /** Custom class name for ColorPicker's dropdown */ 20 | colorFormat: ColorFormat 21 | } 22 | -------------------------------------------------------------------------------- /types/tag.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | export type TagType = 'primary' | 'gray' | 'success' | 'warning' | 'danger' 4 | 5 | /** Tag Component */ 6 | export declare class ElTag extends ElementUIComponent { 7 | /** Theme */ 8 | type: TagType 9 | 10 | /** Whether Tab can be removed */ 11 | closable: boolean 12 | 13 | /** Whether the removal animation is disabled */ 14 | disableTransitions: boolean 15 | 16 | /** Whether Tag has a highlighted border */ 17 | hit: boolean 18 | 19 | /** Background color of the tag */ 20 | color: string 21 | 22 | /** Tag size */ 23 | size: ElementUIComponentSize 24 | } 25 | -------------------------------------------------------------------------------- /examples/assets/images/duotai.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /types/checkbox-button.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Checkbox Button Component */ 4 | export declare class ElCheckboxButton extends ElementUIComponent { 5 | /** Value of the checkbox when used inside a checkbox-group */ 6 | label: string | number | boolean 7 | 8 | /** Value of the checkbox if it's checked */ 9 | trueLabel: string | number 10 | 11 | /** Value of the checkbox if it's not checked */ 12 | falseLabel: string | number 13 | 14 | /** Native 'name' attribute */ 15 | name: string 16 | 17 | /** If the checkbox is disabled */ 18 | disabled: boolean 19 | 20 | /** If the checkbox is checked */ 21 | checked: boolean 22 | } 23 | -------------------------------------------------------------------------------- /types/checkbox-group.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | /** Checkbox Group Component */ 4 | export declare class ElCheckboxGroup extends ElementUIComponent { 5 | /** Size of checkbox buttons or bordered checkboxes */ 6 | size: ElementUIComponentSize 7 | 8 | /** Whether the nesting checkboxes are disabled */ 9 | disabled: boolean 10 | 11 | /** Minimum number of checkbox checked */ 12 | min: number 13 | 14 | /** Maximum number of checkbox checked */ 15 | max: number 16 | 17 | /** Font color when button is active */ 18 | textColor: string 19 | 20 | /** Border and background color when button is active */ 21 | fill: string 22 | } 23 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/common/popup.scss: -------------------------------------------------------------------------------- 1 | @import "../mixins/mixins"; 2 | 3 | .v-modal-enter { 4 | animation: v-modal-in .2s ease; 5 | } 6 | 7 | .v-modal-leave { 8 | animation: v-modal-out .2s ease forwards; 9 | } 10 | 11 | @keyframes v-modal-in { 12 | 0% { 13 | opacity: 0; 14 | } 15 | 100% { 16 | } 17 | } 18 | 19 | @keyframes v-modal-out { 20 | 0% { 21 | } 22 | 100% { 23 | opacity: 0; 24 | } 25 | } 26 | 27 | .v-modal { 28 | position: fixed; 29 | left: 0; 30 | top: 0; 31 | width: 100%; 32 | height: 100%; 33 | opacity: 0.5; 34 | background: #000; 35 | } 36 | 37 | @include b(popup-parent) { 38 | @include m(hidden) { 39 | overflow: hidden; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /types/alert.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type AlertType = 'success' | 'warning' | 'info' | 'error' 4 | 5 | /** Alert Component */ 6 | export declare class ElAlert extends ElementUIComponent { 7 | /** Title */ 8 | title: string 9 | 10 | /** Component type */ 11 | type: AlertType 12 | 13 | /** Descriptive text. Can also be passed with the default slot */ 14 | description: string 15 | 16 | /** If closable or not */ 17 | closable: boolean 18 | 19 | /** whether to center the text */ 20 | center: boolean 21 | 22 | /** Customized close button text */ 23 | closeText: string 24 | 25 | /** If a type icon is displayed */ 26 | showIcon: boolean 27 | } 28 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/date-picker/time-range-picker.scss: -------------------------------------------------------------------------------- 1 | @import "../common/var"; 2 | 3 | @include b(time-range-picker) { 4 | width: 354px; 5 | overflow: visible; 6 | 7 | @include e(content) { 8 | position: relative; 9 | text-align: center; 10 | padding: 10px; 11 | } 12 | 13 | @include e(cell) { 14 | box-sizing: border-box; 15 | margin: 0; 16 | padding: 4px 7px 7px; 17 | width: 50%; 18 | display: inline-block; 19 | } 20 | 21 | @include e(header) { 22 | margin-bottom: 5px; 23 | text-align: center; 24 | font-size: 14px; 25 | } 26 | 27 | @include e(body) { 28 | border-radius:2px; 29 | border: 1px solid $--datepicker-border-color; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/theme-chalk/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var sass = require('gulp-sass'); 5 | var autoprefixer = require('gulp-autoprefixer'); 6 | var cssmin = require('gulp-cssmin'); 7 | 8 | gulp.task('compile', function() { 9 | return gulp.src('./src/*.scss') 10 | .pipe(sass.sync()) 11 | .pipe(autoprefixer({ 12 | browsers: ['ie > 9', 'last 2 versions'], 13 | cascade: false 14 | })) 15 | .pipe(cssmin()) 16 | .pipe(gulp.dest('./lib')); 17 | }); 18 | 19 | gulp.task('copyfont', function() { 20 | return gulp.src('./src/fonts/**') 21 | .pipe(cssmin()) 22 | .pipe(gulp.dest('./lib/fonts')); 23 | }); 24 | 25 | gulp.task('build', ['compile', 'copyfont']); 26 | -------------------------------------------------------------------------------- /src/directives/repeat-click.js: -------------------------------------------------------------------------------- 1 | import { once, on } from 'element-ui/src/utils/dom'; 2 | 3 | export default { 4 | bind(el, binding, vnode) { 5 | let interval = null; 6 | let startTime; 7 | const handler = () => vnode.context[binding.expression].apply(); 8 | const clear = () => { 9 | if (new Date() - startTime < 100) { 10 | handler(); 11 | } 12 | clearInterval(interval); 13 | interval = null; 14 | }; 15 | 16 | on(el, 'mousedown', (e) => { 17 | if (e.button !== 0) return; 18 | startTime = new Date(); 19 | once(document, 'mouseup', clear); 20 | clearInterval(interval); 21 | interval = setInterval(handler, 100); 22 | }); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /test/unit/specs/breadcrumb.spec.js: -------------------------------------------------------------------------------- 1 | import { createVue, destroyVM } from '../util'; 2 | 3 | describe('Breadcrumb', () => { 4 | let vm; 5 | afterEach(() => { 6 | destroyVM(vm); 7 | }); 8 | 9 | it('create', done => { 10 | vm = createVue(` 11 | 12 | 首页 13 | 活动管理 14 | 活动列表 15 | 活动详情 16 | 17 | `); 18 | vm.$nextTick(_ => { 19 | expect(vm.$el.querySelector('.el-breadcrumb__separator').innerText).to.equal('>'); 20 | done(); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/spinner/src/spinner.vue: -------------------------------------------------------------------------------- 1 | 8 | 28 | -------------------------------------------------------------------------------- /examples/icon.json: -------------------------------------------------------------------------------- 1 | ["info","error","success","warning","question","back","arrow-left","arrow-down","arrow-right","arrow-up","caret-left","caret-bottom","caret-top","caret-right","d-arrow-left","d-arrow-right","minus","plus","remove","circle-plus","remove-outline","circle-plus-outline","close","check","circle-close","circle-check","circle-close-outline","circle-check-outline","zoom-out","zoom-in","d-caret","sort","sort-down","sort-up","tickets","document","goods","sold-out","news","message","date","printer","time","bell","mobile-phone","service","view","menu","more","more-outline","star-on","star-off","location","location-outline","phone","phone-outline","picture","picture-outline","delete","search","edit","edit-outline","rank","refresh","share","setting","upload","upload2","download","loading"] -------------------------------------------------------------------------------- /packages/table/src/dropdown.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | var dropdowns = []; 3 | 4 | !Vue.prototype.$isServer && document.addEventListener('click', function(event) { 5 | dropdowns.forEach(function(dropdown) { 6 | var target = event.target; 7 | if (!dropdown || !dropdown.$el) return; 8 | if (target === dropdown.$el || dropdown.$el.contains(target)) { 9 | return; 10 | } 11 | dropdown.handleOutsideClick && dropdown.handleOutsideClick(event); 12 | }); 13 | }); 14 | 15 | export default { 16 | open(instance) { 17 | if (instance) { 18 | dropdowns.push(instance); 19 | } 20 | }, 21 | 22 | close(instance) { 23 | var index = dropdowns.indexOf(instance); 24 | if (index !== -1) { 25 | dropdowns.splice(instance, 1); 26 | } 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /types/row.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Horizontal alignment of flex layout */ 4 | export type HorizontalAlignment = 'start' | 'end' | 'center' | 'space-around' | 'space-between' 5 | 6 | /** vertical alignment of flex layout */ 7 | export type VertialAlignment = 'top' | 'middle' | 'bottom' 8 | 9 | /** Row Layout Component */ 10 | export declare class ElRow extends ElementUIComponent { 11 | /** Grid spacing */ 12 | gutter: number 13 | 14 | /** Layout mode. You can use flex. Works in modern browsers */ 15 | type: string 16 | 17 | /** Horizontal alignment of flex layout */ 18 | justify: HorizontalAlignment 19 | 20 | /** Vertical alignment of flex layout */ 21 | align: VertialAlignment 22 | 23 | /** Custom element tag */ 24 | tag: string 25 | } 26 | -------------------------------------------------------------------------------- /packages/breadcrumb/src/breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 6 | 35 | -------------------------------------------------------------------------------- /packages/tree/src/model/util.js: -------------------------------------------------------------------------------- 1 | export const NODE_KEY = '$treeNodeId'; 2 | 3 | export const markNodeData = function(node, data) { 4 | if (!data || data[NODE_KEY]) return; 5 | Object.defineProperty(data, NODE_KEY, { 6 | value: node.id, 7 | enumerable: false, 8 | configurable: false, 9 | writable: false 10 | }); 11 | }; 12 | 13 | export const getNodeKey = function(key, data) { 14 | if (!key) return data[NODE_KEY]; 15 | return data[key]; 16 | }; 17 | 18 | export const findNearestComponent = (element, componentName) => { 19 | let target = element; 20 | while (target && target.tagName !== 'BODY') { 21 | if (target.__vue__ && target.__vue__.$options.name === componentName) { 22 | return target.__vue__; 23 | } 24 | target = target.parentNode; 25 | } 26 | return null; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/card.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(card) { 5 | border-radius: $--card-border-radius; 6 | border: 1px solid $--card-border-color; 7 | background-color: $--color-white; 8 | overflow: hidden; 9 | color: $--color-text-primary; 10 | transition: 0.3s; 11 | 12 | @include when(always-shadow) { 13 | box-shadow: $--box-shadow-light; 14 | } 15 | 16 | @include when(hover-shadow) { 17 | &:hover, 18 | &:focus { 19 | box-shadow: $--box-shadow-light; 20 | } 21 | } 22 | 23 | @include e(header) { 24 | padding: #{$--card-padding - 2 $--card-padding}; 25 | border-bottom: 1px solid $--card-border-color; 26 | box-sizing: border-box; 27 | } 28 | 29 | @include e(body) { 30 | padding: $--card-padding; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/mixins/utils.scss: -------------------------------------------------------------------------------- 1 | @mixin utils-user-select($value) { 2 | -moz-user-select: $value; 3 | -webkit-user-select: $value; 4 | -ms-user-select: $value; 5 | } 6 | 7 | @mixin utils-clearfix { 8 | $selector: &; 9 | 10 | @at-root { 11 | #{$selector}::before, 12 | #{$selector}::after { 13 | display: table; 14 | content: ""; 15 | } 16 | #{$selector}::after { 17 | clear: both 18 | } 19 | } 20 | } 21 | 22 | @mixin utils-vertical-center { 23 | $selector: &; 24 | 25 | @at-root { 26 | #{$selector}::after { 27 | display: inline-block; 28 | content: ""; 29 | height: 100%; 30 | vertical-align: middle 31 | } 32 | } 33 | } 34 | 35 | @mixin utils-ellipsis { 36 | overflow: hidden; 37 | text-overflow: ellipsis; 38 | white-space: nowrap; 39 | } -------------------------------------------------------------------------------- /packages/dropdown/src/dropdown-item.vue: -------------------------------------------------------------------------------- 1 | 15 | 36 | -------------------------------------------------------------------------------- /types/step.d.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export type StepStatus = 'wait' | 'process' | 'finish' | 'error' | 'success' 5 | 6 | export interface StepRenderSlots { 7 | /** Custom icon */ 8 | icon: VNode[], 9 | 10 | /** Step title */ 11 | title: VNode[], 12 | 13 | /** Step description */ 14 | description: VNode[], 15 | 16 | [key: string]: VNode[] 17 | } 18 | 19 | /** Step Component */ 20 | export declare class ElStep extends ElementUIComponent { 21 | /** Step title */ 22 | title: string 23 | 24 | /** Step description */ 25 | description: string 26 | 27 | /** Step icon */ 28 | icon: string 29 | 30 | /** Current status. It will be automatically set by Steps if not configured. */ 31 | status: StepStatus 32 | 33 | readonly $slots: StepRenderSlots 34 | } 35 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/time-select.scss: -------------------------------------------------------------------------------- 1 | @import "common/var"; 2 | @import "./date-picker/picker.scss"; 3 | @import "./date-picker/date-picker.scss"; 4 | @import "./scrollbar.scss"; 5 | @import "./popper"; 6 | 7 | .time-select { 8 | margin: 5px 0; 9 | min-width: 0; 10 | } 11 | 12 | .time-select .el-picker-panel__content { 13 | max-height: 200px; 14 | margin: 0; 15 | } 16 | 17 | .time-select-item { 18 | padding: 8px 10px; 19 | font-size: 14px; 20 | line-height: 20px; 21 | } 22 | 23 | .time-select-item.selected:not(.disabled) { 24 | color: $--color-primary; 25 | font-weight: bold; 26 | } 27 | 28 | .time-select-item.disabled { 29 | color: $--datepicker-border-color; 30 | cursor: not-allowed; 31 | } 32 | 33 | .time-select-item:hover { 34 | background-color: $--background-color-base; 35 | font-weight: bold; 36 | cursor: pointer; 37 | } 38 | -------------------------------------------------------------------------------- /packages/scrollbar/src/util.js: -------------------------------------------------------------------------------- 1 | export const BAR_MAP = { 2 | vertical: { 3 | offset: 'offsetHeight', 4 | scroll: 'scrollTop', 5 | scrollSize: 'scrollHeight', 6 | size: 'height', 7 | key: 'vertical', 8 | axis: 'Y', 9 | client: 'clientY', 10 | direction: 'top' 11 | }, 12 | horizontal: { 13 | offset: 'offsetWidth', 14 | scroll: 'scrollLeft', 15 | scrollSize: 'scrollWidth', 16 | size: 'width', 17 | key: 'horizontal', 18 | axis: 'X', 19 | client: 'clientX', 20 | direction: 'left' 21 | } 22 | }; 23 | 24 | export function renderThumbStyle({ move, size, bar }) { 25 | const style = {}; 26 | const translate = `translate${bar.axis}(${ move }%)`; 27 | 28 | style[bar.size] = size; 29 | style.transform = translate; 30 | style.msTransform = translate; 31 | style.webkitTransform = translate; 32 | 33 | return style; 34 | }; 35 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/spinner.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | 3 | @include b(time-spinner) { 4 | width: 100%; 5 | white-space: nowrap; 6 | } 7 | 8 | @include b(spinner) { 9 | display: inline-block; 10 | vertical-align: middle; 11 | } 12 | @include b(spinner-inner) { 13 | animation: rotate 2s linear infinite; 14 | width: 50px; 15 | height: 50px; 16 | 17 | & .path { 18 | stroke: #ececec; 19 | stroke-linecap: round; 20 | animation: dash 1.5s ease-in-out infinite; 21 | } 22 | 23 | } 24 | 25 | @keyframes rotate { 26 | 100% { 27 | transform: rotate(360deg); 28 | } 29 | } 30 | 31 | @keyframes dash { 32 | 0% { 33 | stroke-dasharray: 1, 150; 34 | stroke-dashoffset: 0; 35 | } 36 | 50% { 37 | stroke-dasharray: 90, 150; 38 | stroke-dashoffset: -35; 39 | } 40 | 100% { 41 | stroke-dasharray: 90, 150; 42 | stroke-dashoffset: -124; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/container/src/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 34 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/row.scss: -------------------------------------------------------------------------------- 1 | @import "common/var"; 2 | @import "mixins/mixins"; 3 | @import "mixins/utils"; 4 | 5 | @include b(row) { 6 | position: relative; 7 | box-sizing: border-box; 8 | @include utils-clearfix; 9 | 10 | @include m(flex) { 11 | display: flex; 12 | &:before, 13 | &:after { 14 | display: none; 15 | } 16 | 17 | @include when(justify-center) { 18 | justify-content: center; 19 | } 20 | @include when(justify-end) { 21 | justify-content: flex-end; 22 | } 23 | @include when(justify-space-between) { 24 | justify-content: space-between; 25 | } 26 | @include when(justify-space-around) { 27 | justify-content: space-around; 28 | } 29 | 30 | @include when(align-middle) { 31 | align-items: center; 32 | } 33 | @include when(align-bottom) { 34 | align-items: flex-end; 35 | } 36 | } 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/utils/scrollbar-width.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | let scrollBarWidth; 4 | 5 | export default function() { 6 | if (Vue.prototype.$isServer) return 0; 7 | if (scrollBarWidth !== undefined) return scrollBarWidth; 8 | 9 | const outer = document.createElement('div'); 10 | outer.className = 'el-scrollbar__wrap'; 11 | outer.style.visibility = 'hidden'; 12 | outer.style.width = '100px'; 13 | outer.style.position = 'absolute'; 14 | outer.style.top = '-9999px'; 15 | document.body.appendChild(outer); 16 | 17 | const widthNoScroll = outer.offsetWidth; 18 | outer.style.overflow = 'scroll'; 19 | 20 | const inner = document.createElement('div'); 21 | inner.style.width = '100%'; 22 | outer.appendChild(inner); 23 | 24 | const widthWithScroll = inner.offsetWidth; 25 | outer.parentNode.removeChild(outer); 26 | scrollBarWidth = widthNoScroll - widthWithScroll; 27 | 28 | return scrollBarWidth; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/date-picker/src/picker/date-picker.js: -------------------------------------------------------------------------------- 1 | import Picker from '../picker'; 2 | import DatePanel from '../panel/date'; 3 | import DateRangePanel from '../panel/date-range'; 4 | 5 | const getPanel = function(type) { 6 | if (type === 'daterange' || type === 'datetimerange') { 7 | return DateRangePanel; 8 | } 9 | return DatePanel; 10 | }; 11 | 12 | export default { 13 | mixins: [Picker], 14 | 15 | name: 'ElDatePicker', 16 | 17 | props: { 18 | type: { 19 | type: String, 20 | default: 'date' 21 | }, 22 | timeArrowControl: Boolean 23 | }, 24 | 25 | watch: { 26 | type(type) { 27 | if (this.picker) { 28 | this.unmountPicker(); 29 | this.panel = getPanel(type); 30 | this.mountPicker(); 31 | } else { 32 | this.panel = getPanel(type); 33 | } 34 | } 35 | }, 36 | 37 | created() { 38 | this.panel = getPanel(this.type); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /packages/theme-chalk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "element-theme-chalk", 3 | "version": "2.4.9", 4 | "description": "Element component chalk theme.", 5 | "main": "lib/index.css", 6 | "style": "lib/index.css", 7 | "files": [ 8 | "lib", 9 | "src" 10 | ], 11 | "scripts": { 12 | "build": "gulp build" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/ElementUI/theme-chalk.git" 17 | }, 18 | "keywords": [ 19 | "element", 20 | "theme" 21 | ], 22 | "author": "yi.shyang@ele.me", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/ElementUI/theme-chalk/issues" 26 | }, 27 | "homepage": "https://github.com/ElementUI/theme-chalk#readme", 28 | "devDependencies": { 29 | "gulp": "^3.9.1", 30 | "gulp-cssmin": "^0.1.7", 31 | "gulp-sass": "^3.1.0", 32 | "gulp-autoprefixer": "^4.0.0" 33 | }, 34 | "dependencies": {} 35 | } 36 | -------------------------------------------------------------------------------- /types/progress.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type ProgressType = 'line' | 'circle' 4 | export type ProgressStatus = 'success' | 'exception' 5 | 6 | /** Progress Component */ 7 | export declare class ElProgress extends ElementUIComponent { 8 | /** Percentage, required */ 9 | percentage: number 10 | 11 | /** The type of progress bar */ 12 | type: ProgressType 13 | 14 | /** The width of progress bar */ 15 | strokeWidth: number 16 | 17 | /** Whether to place the percentage inside progress bar, only works when type is 'line' */ 18 | textInside: boolean 19 | 20 | /** The current status of progress bar */ 21 | status: ProgressStatus 22 | 23 | /** Background color of progress bar. Overrides `status` prop */ 24 | color: string 25 | 26 | /** The canvas width of circle progress bar */ 27 | width: number 28 | 29 | /** Whether to show percentage */ 30 | showText: boolean 31 | } 32 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/date-picker/month-table.scss: -------------------------------------------------------------------------------- 1 | @import "../common/var"; 2 | 3 | @include b(month-table) { 4 | font-size: 12px; 5 | margin: -1px; 6 | border-collapse: collapse; 7 | 8 | td { 9 | text-align: center; 10 | padding: 20px 3px; 11 | cursor: pointer; 12 | 13 | &.disabled .cell { 14 | background-color: $--background-color-base; 15 | cursor: not-allowed; 16 | color: $--color-text-placeholder; 17 | 18 | &:hover { 19 | color: $--color-text-placeholder; 20 | } 21 | } 22 | 23 | .cell { 24 | width: 48px; 25 | height: 32px; 26 | display: block; 27 | line-height: 32px; 28 | color: $--datepicker-color; 29 | margin: 0 auto; 30 | 31 | &:hover { 32 | color: $--datepicker-text-hover-color; 33 | } 34 | } 35 | 36 | &.current:not(.disabled) .cell { 37 | color: $--datepicker-active-color; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/option-group.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(select-group) { 5 | $gap: 20px; 6 | 7 | margin: 0; 8 | padding: 0; 9 | 10 | @include e(wrap) { 11 | position: relative; 12 | list-style: none; 13 | margin: 0; 14 | padding: 0; 15 | 16 | &:not(:last-of-type) { 17 | padding-bottom: 24px; 18 | 19 | &::after { 20 | content: ''; 21 | position: absolute; 22 | display: block; 23 | left: $gap; 24 | right: $gap; 25 | bottom: 12px; 26 | height: 1px; 27 | background: $--border-color-light; 28 | } 29 | } 30 | } 31 | 32 | @include e(title) { 33 | padding-left: $gap; 34 | font-size: $--select-group-font-size; 35 | color: $--select-group-color; 36 | line-height: $--select-group-height; 37 | } 38 | 39 | & .el-select-dropdown__item { 40 | padding-left: $gap; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/utils/scroll-into-view.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | export default function scrollIntoView(container, selected) { 4 | if (Vue.prototype.$isServer) return; 5 | 6 | if (!selected) { 7 | container.scrollTop = 0; 8 | return; 9 | } 10 | 11 | const offsetParents = []; 12 | let pointer = selected.offsetParent; 13 | while (pointer && container !== pointer && container.contains(pointer)) { 14 | offsetParents.push(pointer); 15 | pointer = pointer.offsetParent; 16 | } 17 | const top = selected.offsetTop + offsetParents.reduce((prev, curr) => (prev + curr.offsetTop), 0); 18 | const bottom = top + selected.offsetHeight; 19 | const viewRectTop = container.scrollTop; 20 | const viewRectBottom = viewRectTop + container.clientHeight; 21 | 22 | if (top < viewRectTop) { 23 | container.scrollTop = top; 24 | } else if (bottom > viewRectBottom) { 25 | container.scrollTop = bottom - container.clientHeight; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /types/dropdown.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | import { ButtonType } from './button' 3 | 4 | export type DropdownMenuAlignment = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' 5 | export type DropdownMenuTrigger = 'hover' | 'click' 6 | 7 | /** Toggleable menu for displaying lists of links and actions */ 8 | export declare class ElDropdown extends ElementUIComponent { 9 | /** Menu button type. only works when split-button is true */ 10 | type: ButtonType 11 | 12 | /** Whether a button group is displayed */ 13 | splitButton: boolean 14 | 15 | /** menu size, also works on the split button */ 16 | size: ElementUIComponentSize 17 | 18 | /** Placement of the menu */ 19 | placement: DropdownMenuAlignment 20 | 21 | /** How to trigger */ 22 | trigger: DropdownMenuTrigger 23 | 24 | /** Whether to hide menu after clicking menu-item */ 25 | hideOnClick: boolean 26 | } 27 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/option.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(select-dropdown) { 5 | @include e(item) { 6 | font-size: $--select-font-size; 7 | padding: 0 20px; 8 | position: relative; 9 | white-space: nowrap; 10 | overflow: hidden; 11 | text-overflow: ellipsis; 12 | color: $--select-option-color; 13 | height: $--select-option-height; 14 | line-height: $--select-option-height; 15 | box-sizing: border-box; 16 | cursor: pointer; 17 | 18 | @include when(disabled) { 19 | color: $--select-option-disabled-color; 20 | cursor: not-allowed; 21 | 22 | &:hover { 23 | background-color: $--color-white; 24 | } 25 | } 26 | 27 | &.hover, &:hover { 28 | background-color: $--select-option-hover-background; 29 | } 30 | 31 | &.selected { 32 | color: $--select-option-selected; 33 | font-weight: bold; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /types/steps.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | import { StepStatus } from './step' 3 | 4 | export type StepsDirection = 'vertical' | 'horizontal' 5 | 6 | /** Guide the user to complete tasks in accordance with the process. Its steps can be set according to the actual application scenario and the number of the steps can't be less than 2. */ 7 | export declare class ElSteps extends ElementUIComponent { 8 | /** The spacing of each step, will be responsive if omitted. Support percentage. */ 9 | space: number | string 10 | 11 | /** Display direction */ 12 | direction: StepsDirection 13 | 14 | /** Current activation step */ 15 | active: number 16 | 17 | /** Status of current step */ 18 | processStatus: StepStatus 19 | 20 | /** Status of end step */ 21 | finishStatus: StepStatus 22 | 23 | /** Whether step description is centered */ 24 | alignCenter: boolean 25 | 26 | /** Whether to apply simple theme */ 27 | simple: boolean 28 | } 29 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/popover.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | @import "./popper"; 4 | 5 | @include b(popover) { 6 | position: absolute; 7 | background: $--popover-fill; 8 | min-width: 150px; 9 | border-radius: 4px; 10 | border: 1px solid $--popover-border-color; 11 | padding: $--popover-padding; 12 | z-index: $--index-popper; 13 | color: $--color-text-regular; 14 | line-height: 1.4; 15 | text-align: justify; 16 | font-size: $--popover-font-size; 17 | box-shadow: $--box-shadow-light; 18 | 19 | @include m(plain) { 20 | padding: $--popover-padding-large; 21 | } 22 | 23 | @include e(title) { 24 | color: $--popover-title-color; 25 | font-size: $--popover-title-font-size; 26 | line-height: 1; 27 | margin-bottom: 12px; 28 | } 29 | 30 | @include e(reference) { 31 | &:focus:not(.focusing), &:focus:hover { 32 | outline-width: 0; 33 | } 34 | } 35 | 36 | &:focus:active, &:focus { 37 | outline-width: 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/date-picker/src/picker/time-picker.js: -------------------------------------------------------------------------------- 1 | import Picker from '../picker'; 2 | import TimePanel from '../panel/time'; 3 | import TimeRangePanel from '../panel/time-range'; 4 | 5 | export default { 6 | mixins: [Picker], 7 | 8 | name: 'ElTimePicker', 9 | 10 | props: { 11 | isRange: Boolean, 12 | arrowControl: Boolean 13 | }, 14 | 15 | data() { 16 | return { 17 | type: '' 18 | }; 19 | }, 20 | 21 | watch: { 22 | isRange(isRange) { 23 | if (this.picker) { 24 | this.unmountPicker(); 25 | this.type = isRange ? 'timerange' : 'time'; 26 | this.panel = isRange ? TimeRangePanel : TimePanel; 27 | this.mountPicker(); 28 | } else { 29 | this.type = isRange ? 'timerange' : 'time'; 30 | this.panel = isRange ? TimeRangePanel : TimePanel; 31 | } 32 | } 33 | }, 34 | 35 | created() { 36 | this.type = this.isRange ? 'timerange' : 'time'; 37 | this.panel = this.isRange ? TimeRangePanel : TimePanel; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/date-picker/year-table.scss: -------------------------------------------------------------------------------- 1 | @import "../common/var"; 2 | 3 | @include b(year-table) { 4 | font-size: 12px; 5 | margin: -1px; 6 | border-collapse: collapse; 7 | 8 | .el-icon { 9 | color: $--datepicker-icon-color; 10 | } 11 | 12 | td { 13 | text-align: center; 14 | padding: 20px 3px; 15 | cursor: pointer; 16 | 17 | &.disabled .cell { 18 | background-color: $--background-color-base; 19 | cursor: not-allowed; 20 | color: $--color-text-placeholder; 21 | 22 | &:hover { 23 | color: $--color-text-placeholder; 24 | } 25 | } 26 | 27 | .cell { 28 | width: 48px; 29 | height: 32px; 30 | display: block; 31 | line-height: 32px; 32 | color: $--datepicker-color; 33 | margin: 0 auto; 34 | 35 | &:hover { 36 | color: $--datepicker-text-hover-color; 37 | } 38 | } 39 | 40 | &.current:not(.disabled) .cell { 41 | color: $--datepicker-active-color; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/utils/after-leave.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bind after-leave event for vue instance. Make sure after-leave is called in any browsers. 3 | * 4 | * @param {Vue} instance Vue instance. 5 | * @param {Function} callback callback of after-leave event 6 | * @param {Number} speed the speed of transition, default value is 300ms 7 | * @param {Boolean} once weather bind after-leave once. default value is false. 8 | */ 9 | export default function(instance, callback, speed = 300, once = false) { 10 | if (!instance || !callback) throw new Error('instance & callback is required'); 11 | let called = false; 12 | const afterLeaveCallback = function() { 13 | if (called) return; 14 | called = true; 15 | if (callback) { 16 | callback.apply(null, arguments); 17 | } 18 | }; 19 | if (once) { 20 | instance.$once('after-leave', afterLeaveCallback); 21 | } else { 22 | instance.$on('after-leave', afterLeaveCallback); 23 | } 24 | setTimeout(() => { 25 | afterLeaveCallback(); 26 | }, speed + 100); 27 | }; 28 | -------------------------------------------------------------------------------- /types/checkbox.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | /** Checkbox Component */ 4 | export declare class ElCheckbox extends ElementUIComponent { 5 | /** The form input value */ 6 | value: string | string[] 7 | 8 | /** Value of the checkbox when used inside a checkbox-group */ 9 | label: string | number | boolean 10 | 11 | /** Value of the checkbox if it's checked */ 12 | trueLabel: string | number 13 | 14 | /** Value of the checkbox if it's not checked */ 15 | falseLabel: string | number 16 | 17 | /** Native 'name' attribute */ 18 | name: string 19 | 20 | /** Whether to add a border around Checkbox */ 21 | border: boolean 22 | 23 | /** Size of the Checkbox, only works when border is true */ 24 | size: ElementUIComponentSize 25 | 26 | /** If the checkbox is disabled */ 27 | disabled: boolean 28 | 29 | /** If the checkbox is checked */ 30 | checked: boolean 31 | 32 | /** Same as indeterminate in native checkbox */ 33 | indeterminate: boolean 34 | } 35 | -------------------------------------------------------------------------------- /types/tabs.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type TabType = 'card' | 'border-card' 4 | export type TabPosition = 'top' | 'right' | 'bottom' | 'left' 5 | 6 | /** Divide data collections which are related yet belong to different types */ 7 | export declare class ElTabs extends ElementUIComponent { 8 | /** Type of Tab */ 9 | type: TabType 10 | 11 | /** Whether Tab is closable */ 12 | closable: boolean 13 | 14 | /** Whether Tab is addable */ 15 | addable: boolean 16 | 17 | /** Whether Tab is addable and closable */ 18 | editable: boolean 19 | 20 | /** Name of the selected tab */ 21 | value: string 22 | 23 | /** Position of tabs */ 24 | tabPosition: TabPosition 25 | 26 | /** Whether width of tab automatically fits its container */ 27 | stretch: Boolean 28 | 29 | /** Hook function before switching tab. If false or a Promise is returned and then is rejected, switching will be prevented */ 30 | beforeLeave: (activeName: string, oldActiveName: string) => boolean | Promise 31 | } 32 | -------------------------------------------------------------------------------- /packages/row/src/row.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'ElRow', 3 | 4 | componentName: 'ElRow', 5 | 6 | props: { 7 | tag: { 8 | type: String, 9 | default: 'div' 10 | }, 11 | gutter: Number, 12 | type: String, 13 | justify: { 14 | type: String, 15 | default: 'start' 16 | }, 17 | align: { 18 | type: String, 19 | default: 'top' 20 | } 21 | }, 22 | 23 | computed: { 24 | style() { 25 | const ret = {}; 26 | 27 | if (this.gutter) { 28 | ret.marginLeft = `-${this.gutter / 2}px`; 29 | ret.marginRight = ret.marginLeft; 30 | } 31 | 32 | return ret; 33 | } 34 | }, 35 | 36 | render(h) { 37 | return h(this.tag, { 38 | class: [ 39 | 'el-row', 40 | this.justify !== 'start' ? `is-justify-${this.justify}` : '', 41 | this.align !== 'top' ? `is-align-${this.align}` : '', 42 | { 'el-row--flex': this.type === 'flex' } 43 | ], 44 | style: this.style 45 | }, this.$slots.default); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /examples/docs/zh-CN/installation.md: -------------------------------------------------------------------------------- 1 | ## 安装 2 | 3 | ### npm 安装 4 | 5 | 推荐使用 npm 的方式安装,它能更好地和 [webpack](https://webpack.js.org/) 打包工具配合使用。 6 | 7 | ```shell 8 | npm i element-ui -S 9 | ``` 10 | 11 | ### CDN 12 | 13 | 目前可以通过 [unpkg.com/element-ui](https://unpkg.com/element-ui/) 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。 14 | 15 | ```html 16 | 17 | 18 | 19 | 20 | ``` 21 | 22 | :::tip 23 | 我们建议使用 CDN 引入 Element 的用户在链接地址上锁定版本,以免将来 Element 升级时受到非兼容性更新的影响。锁定版本的方法请查看 [unpkg.com](https://unpkg.com)。 24 | ::: 25 | 26 | ### Hello world 27 | 28 | 通过 CDN 的方式我们可以很容易地使用 Element 写出一个 Hello world 页面。[在线演示](https://jsfiddle.net/hzfpyvg6/14/) 29 | 30 | 31 | 32 | 如果是通过 npm 安装,并希望配合 webpack 使用,请阅读下一节:[快速上手](/#/zh-CN/component/quickstart)。 33 | -------------------------------------------------------------------------------- /src/mixins/emitter.js: -------------------------------------------------------------------------------- 1 | function broadcast(componentName, eventName, params) { 2 | this.$children.forEach(child => { 3 | var name = child.$options.componentName; 4 | 5 | if (name === componentName) { 6 | child.$emit.apply(child, [eventName].concat(params)); 7 | } else { 8 | broadcast.apply(child, [componentName, eventName].concat([params])); 9 | } 10 | }); 11 | } 12 | export default { 13 | methods: { 14 | dispatch(componentName, eventName, params) { 15 | var parent = this.$parent || this.$root; 16 | var name = parent.$options.componentName; 17 | 18 | while (parent && (!name || name !== componentName)) { 19 | parent = parent.$parent; 20 | 21 | if (parent) { 22 | name = parent.$options.componentName; 23 | } 24 | } 25 | if (parent) { 26 | parent.$emit.apply(parent, [eventName].concat(params)); 27 | } 28 | }, 29 | broadcast(componentName, eventName, params) { 30 | broadcast.call(this, componentName, eventName, params); 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/rate.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(rate) { 5 | height: $--rate-height; 6 | line-height: 1; 7 | 8 | &:focus, &:active { 9 | outline-width: 0; 10 | } 11 | 12 | @include e(item) { 13 | display: inline-block; 14 | position: relative; 15 | font-size: 0; 16 | vertical-align: middle; 17 | } 18 | 19 | @include e(icon) { 20 | position: relative; 21 | display: inline-block; 22 | font-size: $--rate-icon-size; 23 | margin-right: $--rate-icon-margin; 24 | color: $--rate-icon-color; 25 | transition: .3s; 26 | &.hover { 27 | transform: scale(1.15); 28 | } 29 | 30 | .path2 { 31 | position: absolute; 32 | left: 0; 33 | top: 0; 34 | } 35 | } 36 | 37 | @include e(decimal) { 38 | position: absolute; 39 | top: 0; 40 | left: 0; 41 | display: inline-block; 42 | overflow: hidden; 43 | } 44 | 45 | @include e(text) { 46 | font-size: $--rate-font-size; 47 | vertical-align: middle; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /types/input-number.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type InputNumberSize = 'large' | 'small' 4 | 5 | /** InputNumber Component */ 6 | export declare class ElInputNumber extends ElementUIComponent { 7 | /** Binding value */ 8 | value: number 9 | 10 | /** The minimum allowed value */ 11 | min: number 12 | 13 | /** The maximum allowed value */ 14 | max: number 15 | 16 | /** Incremental step */ 17 | step: number 18 | 19 | /** Size of the component */ 20 | size: InputNumberSize 21 | 22 | /** Whether the component is disabled */ 23 | disabled: boolean 24 | 25 | /** Whether to enable the control buttons */ 26 | controls: boolean 27 | 28 | /** Debounce delay when typing, in milliseconds */ 29 | debounce: number 30 | 31 | /** Position of the control buttons */ 32 | controlsPosition: string 33 | 34 | /** Same as name in native input */ 35 | name: string 36 | 37 | /** Precision of input value */ 38 | precision: Number 39 | 40 | /** 41 | * Focus the Input component 42 | */ 43 | focus (): void 44 | } 45 | -------------------------------------------------------------------------------- /types/button.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | /** Button type */ 4 | export type ButtonType = 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'text' 5 | 6 | /** Same as native button's type */ 7 | export type ButtonNativeType = 'button' | 'submit' | 'reset' | 'menu' 8 | 9 | /** Button Component */ 10 | export declare class ElButton extends ElementUIComponent { 11 | /** Button size */ 12 | size: ElementUIComponentSize 13 | 14 | /** Button type */ 15 | type: ButtonType 16 | 17 | /** Determine whether it's a plain button */ 18 | plain: boolean 19 | 20 | /** Determine whether it's a round button */ 21 | round: boolean 22 | 23 | /** Determine whether it's loading */ 24 | loading: boolean 25 | 26 | /** Disable the button */ 27 | disabled: boolean 28 | 29 | /** Button icon, accepts an icon name of Element icon component */ 30 | icon: string 31 | 32 | /** Same as native button's autofocus */ 33 | autofocus: boolean 34 | 35 | /** Same as native button's type */ 36 | nativeType: ButtonNativeType 37 | } 38 | -------------------------------------------------------------------------------- /packages/color-picker/src/draggable.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | let isDragging = false; 3 | 4 | export default function(element, options) { 5 | if (Vue.prototype.$isServer) return; 6 | const moveFn = function(event) { 7 | if (options.drag) { 8 | options.drag(event); 9 | } 10 | }; 11 | const upFn = function(event) { 12 | document.removeEventListener('mousemove', moveFn); 13 | document.removeEventListener('mouseup', upFn); 14 | document.onselectstart = null; 15 | document.ondragstart = null; 16 | 17 | isDragging = false; 18 | 19 | if (options.end) { 20 | options.end(event); 21 | } 22 | }; 23 | element.addEventListener('mousedown', function(event) { 24 | if (isDragging) return; 25 | document.onselectstart = function() { return false; }; 26 | document.ondragstart = function() { return false; }; 27 | 28 | document.addEventListener('mousemove', moveFn); 29 | document.addEventListener('mouseup', upFn); 30 | isDragging = true; 31 | 32 | if (options.start) { 33 | options.start(event); 34 | } 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/unit/specs/badge.spec.js: -------------------------------------------------------------------------------- 1 | import { createTest, createVue, destroyVM } from '../util'; 2 | import Badge from 'packages/badge'; 3 | 4 | describe('Badge', () => { 5 | let vm; 6 | afterEach(() => { 7 | destroyVM(vm); 8 | }); 9 | 10 | it('value', () => { 11 | vm = createTest(Badge, { value: 80 }); 12 | expect(vm.content).to.equal(80); 13 | }); 14 | 15 | it('is fixed', () => { 16 | vm = createVue(` 17 | 18 | 19 | 20 | `); 21 | 22 | expect(vm.$el.querySelector('.el-badge__content.is-fixed')).to.exist; 23 | }); 24 | 25 | it('is dot', () => { 26 | vm = createVue(` 27 | 28 | 29 | 30 | `); 31 | 32 | expect(vm.$el.querySelector('.el-badge__content.is-dot')).to.exist; 33 | }); 34 | 35 | it('max', () => { 36 | vm = createTest(Badge, { max: 100, value: 200 }); 37 | expect(vm.content).to.equal('100+'); 38 | vm = createTest(Badge, { max: 100, value: 80 }); 39 | expect(vm.content).to.equal(80); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/mixins/function.scss: -------------------------------------------------------------------------------- 1 | @import "config"; 2 | 3 | /* BEM support Func 4 | -------------------------- */ 5 | @function selectorToString($selector) { 6 | $selector: inspect($selector); 7 | $selector: str-slice($selector, 2, -2); 8 | @return $selector; 9 | } 10 | 11 | @function containsModifier($selector) { 12 | $selector: selectorToString($selector); 13 | 14 | @if str-index($selector, $modifier-separator) { 15 | @return true; 16 | } @else { 17 | @return false; 18 | } 19 | } 20 | 21 | @function containWhenFlag($selector) { 22 | $selector: selectorToString($selector); 23 | 24 | @if str-index($selector, '.' + $state-prefix) { 25 | @return true 26 | } @else { 27 | @return false 28 | } 29 | } 30 | 31 | @function containPseudoClass($selector) { 32 | $selector: selectorToString($selector); 33 | 34 | @if str-index($selector, ':') { 35 | @return true 36 | } @else { 37 | @return false 38 | } 39 | } 40 | 41 | @function hitAllSpecialNestRule($selector) { 42 | 43 | @return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector); 44 | } 45 | -------------------------------------------------------------------------------- /packages/checkbox/src/checkbox-group.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 49 | -------------------------------------------------------------------------------- /examples/assets/styles/fonts/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icomoon'; 3 | src: url('icomoon.eot?h6xgdm'); 4 | src: url('icomoon.eot?h6xgdm#iefix') format('embedded-opentype'), 5 | url('icomoon.ttf?h6xgdm') format('truetype'), 6 | url('icomoon.woff?h6xgdm') format('woff'), 7 | url('icomoon.svg?h6xgdm#icomoon') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | [class^="icon-"], [class*=" icon-"] { 13 | /* use !important to prevent issues with browser extensions that change fonts */ 14 | font-family: 'icomoon' !important; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | 22 | /* Better Font Rendering =========== */ 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .icon-rate-face-off:before { 28 | content: "\e900"; 29 | } 30 | .icon-rate-face-1:before { 31 | content: "\e901"; 32 | } 33 | .icon-rate-face-2:before { 34 | content: "\e902"; 35 | } 36 | .icon-rate-face-3:before { 37 | content: "\e903"; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /types/switch.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Switch Component */ 4 | export declare class ElSwitch extends ElementUIComponent { 5 | /** Whether Switch is on */ 6 | value: boolean 7 | 8 | /** Whether Switch is disabled */ 9 | disabled: boolean 10 | 11 | /** Width of Switch */ 12 | width: number 13 | 14 | /** Class name of the icon displayed when in on state, overrides on-text */ 15 | activeIconClass: string 16 | 17 | /** Class name of the icon displayed when in off state, overrides off-text */ 18 | inactiveIconClass: string 19 | 20 | /** Text displayed when in on state */ 21 | activeText: string 22 | 23 | /** Text displayed when in off state */ 24 | inactiveText: string 25 | 26 | /** Background color when in on state */ 27 | activeColor: string 28 | 29 | /** Background color when in off state */ 30 | inactiveColor: string 31 | 32 | /** Switch value when in on state */ 33 | activeValue: string | boolean | number 34 | 35 | /** Switch value when in off state */ 36 | inactiveValue: string | boolean | number 37 | 38 | /** Input name of Switch */ 39 | name: string 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-present ElemeFE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/utils/resize-event.js: -------------------------------------------------------------------------------- 1 | import ResizeObserver from 'resize-observer-polyfill'; 2 | 3 | const isServer = typeof window === 'undefined'; 4 | 5 | /* istanbul ignore next */ 6 | const resizeHandler = function(entries) { 7 | for (let entry of entries) { 8 | const listeners = entry.target.__resizeListeners__ || []; 9 | if (listeners.length) { 10 | listeners.forEach(fn => { 11 | fn(); 12 | }); 13 | } 14 | } 15 | }; 16 | 17 | /* istanbul ignore next */ 18 | export const addResizeListener = function(element, fn) { 19 | if (isServer) return; 20 | if (!element.__resizeListeners__) { 21 | element.__resizeListeners__ = []; 22 | element.__ro__ = new ResizeObserver(resizeHandler); 23 | element.__ro__.observe(element); 24 | } 25 | element.__resizeListeners__.push(fn); 26 | }; 27 | 28 | /* istanbul ignore next */ 29 | export const removeResizeListener = function(element, fn) { 30 | if (!element || !element.__resizeListeners__) return; 31 | element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); 32 | if (!element.__resizeListeners__.length) { 33 | element.__ro__.disconnect(); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/locale/format.js: -------------------------------------------------------------------------------- 1 | import { hasOwn } from 'element-ui/src/utils/util'; 2 | 3 | const RE_NARGS = /(%|)\{([0-9a-zA-Z_]+)\}/g; 4 | /** 5 | * String format template 6 | * - Inspired: 7 | * https://github.com/Matt-Esch/string-template/index.js 8 | */ 9 | export default function(Vue) { 10 | 11 | /** 12 | * template 13 | * 14 | * @param {String} string 15 | * @param {Array} ...args 16 | * @return {String} 17 | */ 18 | 19 | function template(string, ...args) { 20 | if (args.length === 1 && typeof args[0] === 'object') { 21 | args = args[0]; 22 | } 23 | 24 | if (!args || !args.hasOwnProperty) { 25 | args = {}; 26 | } 27 | 28 | return string.replace(RE_NARGS, (match, prefix, i, index) => { 29 | let result; 30 | 31 | if (string[index - 1] === '{' && 32 | string[index + match.length] === '}') { 33 | return i; 34 | } else { 35 | result = hasOwn(args, i) ? args[i] : null; 36 | if (result === null || result === undefined) { 37 | return ''; 38 | } 39 | 40 | return result; 41 | } 42 | }); 43 | } 44 | 45 | return template; 46 | } 47 | -------------------------------------------------------------------------------- /types/pagination.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Pagination Component */ 4 | export declare class ElPagination extends ElementUIComponent { 5 | /** Whether to use small pagination */ 6 | small: boolean 7 | 8 | /** Item count of each page */ 9 | pageSize: number 10 | 11 | /** Total item count */ 12 | total: number 13 | 14 | /** Total page count. Set either total or page-count and pages will be displayed; if you need page-sizes, total is required */ 15 | pageCount: number 16 | 17 | /** Number of pagers */ 18 | pagerCount: number 19 | 20 | /** Current page number */ 21 | currentPage: number 22 | 23 | /** 24 | * Layout of Pagination. Elements separated with a comma. 25 | * Accepted values: `sizes`, `prev`, `pager`, `next`, `jumper`, `->`, `total`, `slot` 26 | */ 27 | layout: string 28 | 29 | /** Options of item count per page */ 30 | pageSizes: number[] 31 | 32 | /** Custom class name for the page size Select's dropdown */ 33 | popperClass: string 34 | 35 | /** Text for the prev button */ 36 | prevText: string 37 | 38 | /** Text for the prev button */ 39 | nextText: string 40 | } 41 | -------------------------------------------------------------------------------- /packages/loading/src/loading.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 42 | -------------------------------------------------------------------------------- /packages/menu/src/menu-item-group.vue: -------------------------------------------------------------------------------- 1 | 12 | 45 | 46 | -------------------------------------------------------------------------------- /packages/tag/src/tag.vue: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /types/form-item.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | /** FormItem Component */ 4 | export declare class ElFormItem extends ElementUIComponent { 5 | /** A key of `model` of the enclosing `el-form` component */ 6 | prop: string 7 | 8 | /** Label */ 9 | label: string 10 | 11 | /** Width of label, e.g. '50px' */ 12 | labelWidth: string 13 | 14 | /** Whether the field is required or not, will be determined by validation rules if omitted */ 15 | required: boolean 16 | 17 | /** Validation rules of form */ 18 | rules: object 19 | 20 | /** Field error message, set its value and the field will validate error and show this message immediately */ 21 | error: string 22 | 23 | /** Whether to show the error message */ 24 | showMessage: boolean 25 | 26 | /** Whether to display the error message inline with the form item */ 27 | inlineMessage: boolean 28 | 29 | /** Controls the size of components in this form */ 30 | size: ElementUIComponentSize 31 | 32 | /** Reset current field and remove validation result */ 33 | resetField (): void 34 | 35 | /** Remove validation status of the field */ 36 | clearValidate (): void 37 | } 38 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/carousel-item.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(carousel) { 5 | @include e(item) { 6 | position: absolute; 7 | top: 0; 8 | left: 0; 9 | width: 100%; 10 | height: 100%; 11 | display: inline-block; 12 | overflow: hidden; 13 | z-index: #{$--index-normal - 1}; 14 | 15 | @include when(active) { 16 | z-index: #{$--index-normal + 1}; 17 | } 18 | 19 | @include when(animating) { 20 | transition: transform .4s ease-in-out; 21 | } 22 | 23 | @include m(card) { 24 | width: 50%; 25 | transition: transform .4s ease-in-out; 26 | &.is-in-stage { 27 | cursor: pointer; 28 | z-index: $--index-normal; 29 | &:hover .el-carousel__mask, 30 | &.is-hover .el-carousel__mask { 31 | opacity: 0.12; 32 | } 33 | } 34 | &.is-active { 35 | z-index: #{$--index-normal + 1}; 36 | } 37 | } 38 | } 39 | 40 | @include e(mask) { 41 | position: absolute; 42 | width: 100%; 43 | height: 100%; 44 | top: 0; 45 | left: 0; 46 | background-color: $--color-white; 47 | opacity: 0.24; 48 | transition: .2s; 49 | } 50 | } -------------------------------------------------------------------------------- /examples/docs/en-US/installation.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | 3 | ### npm 4 | 5 | Installing with npm is recommended and it works seamlessly with [webpack](https://webpack.js.org/). 6 | 7 | ```shell 8 | npm i element-ui -S 9 | ``` 10 | 11 | ### CDN 12 | 13 | Get the latest version from [unpkg.com/element-ui](https://unpkg.com/element-ui/) , and import JavaScript and CSS file in your page. 14 | 15 | ```html 16 | 17 | 18 | 19 | 20 | ``` 21 | 22 | :::tip 23 | We recommend our users to lock Element's version when using CDN. Please refer to [unpkg.com](https://unpkg.com) for more information. 24 | ::: 25 | 26 | ### Hello world 27 | 28 | If you are using CDN, a hello-world page is easy with Element. [Online Demo](https://jsfiddle.net/hzfpyvg6/14/) 29 | 30 | 31 | 32 | If you are using npm and wish to apply webpack, please continue to the next page: [Quick Start](/#/en-US/component/quickstart). 33 | -------------------------------------------------------------------------------- /packages/breadcrumb/src/breadcrumb-item.vue: -------------------------------------------------------------------------------- 1 | 13 | 42 | -------------------------------------------------------------------------------- /packages/badge/src/main.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 54 | -------------------------------------------------------------------------------- /packages/menu/src/menu-mixin.js: -------------------------------------------------------------------------------- 1 | export default { 2 | inject: ['rootMenu'], 3 | computed: { 4 | indexPath() { 5 | const path = [this.index]; 6 | let parent = this.$parent; 7 | while (parent.$options.componentName !== 'ElMenu') { 8 | if (parent.index) { 9 | path.unshift(parent.index); 10 | } 11 | parent = parent.$parent; 12 | } 13 | return path; 14 | }, 15 | parentMenu() { 16 | let parent = this.$parent; 17 | while ( 18 | parent && 19 | ['ElMenu', 'ElSubmenu'].indexOf(parent.$options.componentName) === -1 20 | ) { 21 | parent = parent.$parent; 22 | } 23 | return parent; 24 | }, 25 | paddingStyle() { 26 | if (this.rootMenu.mode !== 'vertical') return {}; 27 | 28 | let padding = 20; 29 | let parent = this.$parent; 30 | 31 | if (this.rootMenu.collapse) { 32 | padding = 20; 33 | } else { 34 | while (parent && parent.$options.componentName !== 'ElMenu') { 35 | if (parent.$options.componentName === 'ElSubmenu') { 36 | padding += 20; 37 | } 38 | parent = parent.$parent; 39 | } 40 | } 41 | return {paddingLeft: padding + 'px'}; 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/breadcrumb.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "mixins/utils"; 3 | @import "common/var"; 4 | 5 | @include b(breadcrumb) { 6 | font-size: 14px; 7 | line-height: 1; 8 | @include utils-clearfix; 9 | 10 | @include e(separator) { 11 | margin: 0 9px; 12 | font-weight: bold; 13 | color: $--color-text-placeholder; 14 | 15 | &[class*=icon] { 16 | margin: 0 6px; 17 | font-weight: normal; 18 | } 19 | } 20 | 21 | @include e(item) { 22 | float: left; 23 | 24 | @include e(inner) { 25 | color: $--color-text-regular; 26 | 27 | &.is-link, & a { 28 | font-weight: bold; 29 | text-decoration: none; 30 | transition: $--color-transition-base; 31 | color: $--color-text-primary; 32 | 33 | &:hover { 34 | color: $--color-primary; 35 | cursor: pointer; 36 | } 37 | } 38 | } 39 | 40 | &:last-child { 41 | .el-breadcrumb__inner, 42 | .el-breadcrumb__inner a { 43 | &, &:hover { 44 | font-weight: normal; 45 | color: $--color-text-regular; 46 | cursor: text; 47 | } 48 | } 49 | 50 | .el-breadcrumb__separator { 51 | display: none; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/unit/specs/row.spec.js: -------------------------------------------------------------------------------- 1 | import { createTest, destroyVM } from '../util'; 2 | import Row from 'packages/row'; 3 | 4 | describe('Row', () => { 5 | let vm; 6 | afterEach(() => { 7 | destroyVM(vm); 8 | }); 9 | 10 | it('create', () => { 11 | vm = createTest(Row, true); 12 | let rowElm = vm.$el; 13 | expect(rowElm.classList.contains('el-row')).to.be.true; 14 | }); 15 | it('gutter', () => { 16 | vm = createTest(Row, { 17 | gutter: 20 18 | }, true); 19 | let rowElm = vm.$el; 20 | expect(rowElm.style.marginLeft).to.be.equal('-10px'); 21 | expect(rowElm.style.marginRight).to.be.equal('-10px'); 22 | }); 23 | it('type', () => { 24 | vm = createTest(Row, { 25 | type: 'flex' 26 | }, true); 27 | let rowElm = vm.$el; 28 | expect(rowElm.classList.contains('el-row--flex')).to.be.true; 29 | }); 30 | it('justify', () => { 31 | vm = createTest(Row, { 32 | justify: 'end' 33 | }, true); 34 | let rowElm = vm.$el; 35 | expect(rowElm.classList.contains('is-justify-end')).to.be.true; 36 | }); 37 | it('align', () => { 38 | vm = createTest(Row, { 39 | align: 'bottom' 40 | }, true); 41 | let rowElm = vm.$el; 42 | expect(rowElm.classList.contains('is-align-bottom')).to.be.true; 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /examples/docs/es/installation.md: -------------------------------------------------------------------------------- 1 | ## Instalación 2 | 3 | ### npm 4 | 5 | Instalar mediante npm es la forma recomendada ya que se integra facilmente con [webpack](https://webpack.js.org/). 6 | 7 | ```shell 8 | npm i element-ui -S 9 | ``` 10 | 11 | ### CDN 12 | 13 | Obtenga la última versión desde [unpkg.com/element-ui](https://unpkg.com/element-ui/) , e importe el JavaScript y los archivos CSS en su página. 14 | 15 | ```html 16 | 17 | 18 | 19 | 20 | ``` 21 | 22 | ##Tip 23 | Recomendamos a nuestros usuarios congelar la versión de Elemet cuando usas un CDN. Por favor, refiérase a [unpkg.com](https://unpkg.com) para más información. 24 | 25 | ### Hello world 26 | 27 | Si esta usando un CDN, una página con Hello-World es fácil con Element. [Online Demo](https://jsfiddle.net/hzfpyvg6/14/) 28 | 29 | 30 | 31 | Si esta usando npm y desea combinarlo con webpack, por favor continue a la siguiente página: [Quick Start](/#/es/component/quickstart) 32 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: dist test 2 | default: help 3 | 4 | # build all theme 5 | build-theme: 6 | npm run build:theme 7 | 8 | install: 9 | npm install 10 | 11 | install-cn: 12 | npm install --registry=http://registry.npm.taobao.org 13 | 14 | dev: 15 | npm run dev 16 | 17 | play: 18 | npm run dev:play 19 | 20 | new: 21 | node build/bin/new.js $(filter-out $@,$(MAKECMDGOALS)) 22 | 23 | new-lang: 24 | node build/bin/new-lang.js $(filter-out $@,$(MAKECMDGOALS)) 25 | 26 | dist: install 27 | npm run dist 28 | 29 | deploy: 30 | @npm run deploy 31 | 32 | pub: 33 | npm run pub 34 | 35 | test: 36 | npm run test:watch 37 | 38 | help: 39 | @echo " \033[35mmake\033[0m \033[1m命令使用说明\033[0m" 40 | @echo " \033[35mmake install\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 安装依赖" 41 | @echo " \033[35mmake new [中文名]\033[0m\t--- 创建新组件 package. 例如 'make new button 按钮'" 42 | @echo " \033[35mmake dev\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 开发模式" 43 | @echo " \033[35mmake dist\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 编译项目,生成目标文件" 44 | @echo " \033[35mmake deploy\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 部署 demo" 45 | @echo " \033[35mmake pub\033[0m\t\033[0m\t\033[0m\t\033[0m\t--- 发布到 npm 上" 46 | @echo " \033[35mmake new-lang \033[0m\t\033[0m\t\033[0m\t--- 为网站添加新语言. 例如 'make new-lang fr'" 47 | -------------------------------------------------------------------------------- /examples/entry.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import entry from './app'; 3 | import VueRouter from 'vue-router'; 4 | import Element from 'main/index.js'; 5 | import 'packages/theme-chalk/src/index.scss'; 6 | import routes from './route.config'; 7 | import demoBlock from './components/demo-block.vue'; 8 | import MainFooter from './components/footer.vue'; 9 | import MainHeader from './components/header.vue'; 10 | import SideNav from './components/side-nav'; 11 | import FooterNav from './components/footer-nav'; 12 | import title from './i18n/title.json'; 13 | 14 | Vue.use(Element); 15 | Vue.use(VueRouter); 16 | Vue.component('demo-block', demoBlock); 17 | Vue.component('main-footer', MainFooter); 18 | Vue.component('main-header', MainHeader); 19 | Vue.component('side-nav', SideNav); 20 | Vue.component('footer-nav', FooterNav); 21 | 22 | const router = new VueRouter({ 23 | mode: 'hash', 24 | base: __dirname, 25 | routes 26 | }); 27 | 28 | router.afterEach(route => { 29 | const data = title[route.meta.lang]; 30 | for (let val in data) { 31 | if (new RegExp('^' + val, 'g').test(route.name)) { 32 | document.title = data[val]; 33 | return; 34 | } 35 | } 36 | document.title = 'Element'; 37 | }); 38 | 39 | new Vue({ // eslint-disable-line 40 | render: h => h(entry), 41 | router 42 | }).$mount('#app'); 43 | -------------------------------------------------------------------------------- /packages/tabs/src/tab-pane.vue: -------------------------------------------------------------------------------- 1 | 14 | 59 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | var webpackConfig = require('../../build/webpack.test'); 2 | 3 | // no need for app entry during tests 4 | // delete webpackConfig.entry; 5 | 6 | module.exports = function(config) { 7 | var configuration = { 8 | // to run in additional browsers: 9 | // 1. install corresponding karma launcher 10 | // http://karma-runner.github.io/0.13/config/browsers.html 11 | // 2. add it to the `browsers` array below. 12 | browsers: ['Chrome'], 13 | customLaunchers: { 14 | Chrome_travis_ci: { 15 | base: 'Chrome', 16 | flags: ['--no-sandbox'] 17 | } 18 | }, 19 | frameworks: ['mocha', 'sinon-chai'], 20 | reporters: ['spec', 'coverage'], 21 | files: ['./index.js'], 22 | preprocessors: { 23 | './index.js': ['webpack', 'sourcemap'] 24 | }, 25 | webpack: webpackConfig, 26 | webpackMiddleware: { 27 | noInfo: true 28 | }, 29 | coverageReporter: { 30 | dir: './coverage', 31 | reporters: [ 32 | { type: 'lcov', subdir: '.' }, 33 | { type: 'text-summary' } 34 | ] 35 | }, 36 | client: { 37 | mocha: { 38 | timeout: 4000 39 | } 40 | } 41 | }; 42 | 43 | if (process.env.TRAVIS) { 44 | configuration.browsers = ['Chrome_travis_ci']; 45 | } 46 | 47 | config.set(configuration); 48 | }; 49 | -------------------------------------------------------------------------------- /types/col.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Responsive column props */ 4 | export interface ResponsiveColumnProperties { 5 | /** Number of column the grid spans */ 6 | span: number, 7 | 8 | /** Number of spacing on the left side of the grid */ 9 | offset: number 10 | } 11 | 12 | /** Responsive column property */ 13 | export type ResponsiveColumn = number | ResponsiveColumnProperties 14 | 15 | /** Colunm Layout Component */ 16 | export declare class ElCol extends ElementUIComponent { 17 | /** Number of column the grid spans */ 18 | span: number 19 | 20 | /** Number of spacing on the left side of the grid */ 21 | offset: number 22 | 23 | /** Number of columns that grid moves to the right */ 24 | push: number 25 | 26 | /** Number of columns that grid moves to the left */ 27 | pull: number 28 | 29 | /** <768px Responsive columns or column props object */ 30 | xs: ResponsiveColumn 31 | 32 | /** ≥768px Responsive columns or column props object */ 33 | sm: ResponsiveColumn 34 | 35 | /** ≥992px Responsive columns or column props object */ 36 | md: ResponsiveColumn 37 | 38 | /** ≥1200px Responsive columns or column props object */ 39 | lg: ResponsiveColumn 40 | 41 | /** ≥1920px Responsive columns or column props object */ 42 | xl: ResponsiveColumn 43 | 44 | /** custom element tag */ 45 | tag: string 46 | } 47 | -------------------------------------------------------------------------------- /packages/steps/src/steps.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 69 | -------------------------------------------------------------------------------- /types/tooltip.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | import { PopoverPlacement } from './popover' 3 | 4 | export type TooltipEffect = 'dark' | 'light' 5 | 6 | /** Tooltip Component */ 7 | export declare class ElTooltip extends ElementUIComponent { 8 | /** Tooltip theme */ 9 | effect: TooltipEffect 10 | 11 | /** Display content, can be overridden by slot#content */ 12 | content: String 13 | 14 | /** Position of Tooltip */ 15 | placement: PopoverPlacement 16 | 17 | /** Visibility of Tooltip */ 18 | value: boolean 19 | 20 | /** Whether Tooltip is disabled */ 21 | disabled: boolean 22 | 23 | /** Offset of the Tooltip */ 24 | offset: number 25 | 26 | /** Animation name */ 27 | transition: string 28 | 29 | /** Whether an arrow is displayed. For more information, check Vue-popper page */ 30 | visibleArrow: boolean 31 | 32 | /** Popper.js parameters */ 33 | popperOptions: object 34 | 35 | /** Delay of appearance, in millisecond */ 36 | openDelay: number 37 | 38 | /** Whether to control Tooltip manually. mouseenter and mouseleave won't have effects if set to true */ 39 | manual: boolean 40 | 41 | /** Custom class name for Tooltip's popper */ 42 | popperClass: string 43 | 44 | /** Whether the mouse can enter the tooltip */ 45 | enterable: string 46 | 47 | /** Timeout in milliseconds to hide tooltip */ 48 | hideAfter: string 49 | } 50 | -------------------------------------------------------------------------------- /src/locale/index.js: -------------------------------------------------------------------------------- 1 | import defaultLang from 'element-ui/src/locale/lang/zh-CN'; 2 | import Vue from 'vue'; 3 | import deepmerge from 'deepmerge'; 4 | import Format from './format'; 5 | 6 | const format = Format(Vue); 7 | let lang = defaultLang; 8 | let merged = false; 9 | let i18nHandler = function() { 10 | const vuei18n = Object.getPrototypeOf(this || Vue).$t; 11 | if (typeof vuei18n === 'function' && !!Vue.locale) { 12 | if (!merged) { 13 | merged = true; 14 | Vue.locale( 15 | Vue.config.lang, 16 | deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true }) 17 | ); 18 | } 19 | return vuei18n.apply(this, arguments); 20 | } 21 | }; 22 | 23 | export const t = function(path, options) { 24 | let value = i18nHandler.apply(this, arguments); 25 | if (value !== null && value !== undefined) return value; 26 | 27 | const array = path.split('.'); 28 | let current = lang; 29 | 30 | for (let i = 0, j = array.length; i < j; i++) { 31 | const property = array[i]; 32 | value = current[property]; 33 | if (i === j - 1) return format(value, options); 34 | if (!value) return ''; 35 | current = value; 36 | } 37 | return ''; 38 | }; 39 | 40 | export const use = function(l) { 41 | lang = l || lang; 42 | }; 43 | 44 | export const i18n = function(fn) { 45 | i18nHandler = fn || i18nHandler; 46 | }; 47 | 48 | export default { use, t, i18n }; 49 | -------------------------------------------------------------------------------- /packages/select/src/option-group.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 61 | -------------------------------------------------------------------------------- /types/time-select.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize, ElementUIHorizontalAlignment } from './component' 2 | 3 | export interface TimeSelectOptions { 4 | /** Start time */ 5 | start?: string, 6 | 7 | /** End time */ 8 | end?: string, 9 | 10 | /** Time step */ 11 | step?: string, 12 | 13 | /** Minimum time, any time before this time will be disabled */ 14 | minTime?: string, 15 | 16 | /** Maximum time, any time after this time will be disabled */ 17 | maxTime?: string 18 | } 19 | 20 | /** TimeSelect Component */ 21 | export declare class ElTimeSelect extends ElementUIComponent { 22 | /** Whether DatePicker is read only */ 23 | readonly: boolean 24 | 25 | /** Whether DatePicker is disabled */ 26 | disabled: boolean 27 | 28 | /** Whether the input is editable */ 29 | editable: boolean 30 | 31 | /** Whether to show clear button */ 32 | clearable: boolean 33 | 34 | /** Size of Input */ 35 | size: ElementUIComponentSize 36 | 37 | /** Placeholder */ 38 | placeholder: string 39 | 40 | /** Value of the picker */ 41 | value: string | Date 42 | 43 | /** Alignment */ 44 | align: ElementUIHorizontalAlignment 45 | 46 | /** Custom class name for TimePicker's dropdown */ 47 | popperClass: string 48 | 49 | /** Additional options, check the table below */ 50 | pickerOptions: TimeSelectOptions 51 | 52 | /** 53 | * Focus the Input component 54 | */ 55 | focus (): void 56 | } 57 | -------------------------------------------------------------------------------- /packages/dropdown/src/dropdown-menu.vue: -------------------------------------------------------------------------------- 1 | 8 | 61 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/scrollbar.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(scrollbar) { 5 | overflow: hidden; 6 | position: relative; 7 | 8 | &:hover, 9 | &:active, 10 | &:focus { 11 | > .el-scrollbar__bar { 12 | opacity: 1; 13 | transition: opacity 340ms ease-out; 14 | } 15 | } 16 | 17 | @include e(wrap) { 18 | overflow: scroll; 19 | height: 100%; 20 | 21 | @include m(hidden-default) { 22 | &::-webkit-scrollbar { 23 | width: 0; 24 | height: 0; 25 | } 26 | } 27 | } 28 | 29 | @include e(thumb) { 30 | position: relative; 31 | display: block; 32 | width: 0; 33 | height: 0; 34 | cursor: pointer; 35 | border-radius: inherit; 36 | background-color: $--scrollbar-background-color; 37 | transition: .3s background-color; 38 | 39 | &:hover { 40 | background-color: $--scrollbar-hover-background-color; 41 | } 42 | } 43 | 44 | @include e(bar) { 45 | position: absolute; 46 | right: 2px; 47 | bottom: 2px; 48 | z-index: 1; 49 | border-radius: 4px; 50 | opacity: 0; 51 | transition: opacity 120ms ease-out; 52 | 53 | @include when(vertical) { 54 | width: 6px; 55 | top: 2px; 56 | 57 | > div { 58 | width: 100%; 59 | } 60 | } 61 | 62 | @include when(horizontal) { 63 | height: 6px; 64 | left: 2px; 65 | 66 | > div { 67 | height: 100%; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /types/menu.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type MenuDisplayMode = 'horizontal' | 'vertical' 4 | export type MenuTheme = 'light' | 'dark' 5 | 6 | /** Menu that provides navigation for your website */ 7 | export declare class ElMenu extends ElementUIComponent { 8 | /** Menu display mode */ 9 | mode: MenuDisplayMode 10 | 11 | /** Whether the menu is collapsed (available only in vertical mode) */ 12 | collapse: boolean 13 | 14 | /** Background color of Menu (hex format) */ 15 | backgroundColor: string 16 | 17 | /** Text color of Menu (hex format) */ 18 | textColor: string 19 | 20 | /** Text color of currently active menu item (hex format) */ 21 | activeTextColor: string 22 | 23 | /** Index of currently active menu */ 24 | defaultActive: string 25 | 26 | /** Array that contains keys of currently active sub-menus */ 27 | defaultOpeneds: string[] 28 | 29 | /** Whether only one sub-menu can be active */ 30 | uniqueOpened: boolean 31 | 32 | /** How sub-menus are triggered, only works when mode is 'horizontal' */ 33 | menuTrigger: string 34 | 35 | /** Whether vue-router mode is activated. If true, index will be used as 'path' to activate the route action */ 36 | router: boolean 37 | 38 | /** Whether the menu collapse transition is active */ 39 | collapseTransition: boolean 40 | 41 | /** Open the specified sub-menu */ 42 | open (index: string): void 43 | 44 | /** Close the specified sub-menu */ 45 | close (index: string): void 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/menu/aria-menuitem.js: -------------------------------------------------------------------------------- 1 | import Utils from '../aria-utils'; 2 | import SubMenu from './aria-submenu'; 3 | 4 | const MenuItem = function(domNode) { 5 | this.domNode = domNode; 6 | this.submenu = null; 7 | this.init(); 8 | }; 9 | 10 | MenuItem.prototype.init = function() { 11 | this.domNode.setAttribute('tabindex', '0'); 12 | let menuChild = this.domNode.querySelector('.el-menu'); 13 | if (menuChild) { 14 | this.submenu = new SubMenu(this, menuChild); 15 | } 16 | this.addListeners(); 17 | }; 18 | 19 | MenuItem.prototype.addListeners = function() { 20 | const keys = Utils.keys; 21 | this.domNode.addEventListener('keydown', event => { 22 | let prevDef = false; 23 | switch (event.keyCode) { 24 | case keys.down: 25 | Utils.triggerEvent(event.currentTarget, 'mouseenter'); 26 | this.submenu && this.submenu.gotoSubIndex(0); 27 | prevDef = true; 28 | break; 29 | case keys.up: 30 | Utils.triggerEvent(event.currentTarget, 'mouseenter'); 31 | this.submenu && this.submenu.gotoSubIndex(this.submenu.subMenuItems.length - 1); 32 | prevDef = true; 33 | break; 34 | case keys.tab: 35 | Utils.triggerEvent(event.currentTarget, 'mouseleave'); 36 | break; 37 | case keys.enter: 38 | case keys.space: 39 | prevDef = true; 40 | event.currentTarget.click(); 41 | break; 42 | } 43 | if (prevDef) { 44 | event.preventDefault(); 45 | } 46 | }); 47 | }; 48 | 49 | export default MenuItem; 50 | -------------------------------------------------------------------------------- /test/unit/specs/card.spec.js: -------------------------------------------------------------------------------- 1 | import { createVue, createTest, destroyVM } from '../util'; 2 | import Card from 'packages/card'; 3 | 4 | describe('Card', () => { 5 | let vm; 6 | afterEach(() => { 7 | destroyVM(vm); 8 | }); 9 | 10 | it('slot:header', () => { 11 | vm = createVue(` 12 | 13 |
二师兄叫我埋梗 啦啦啦
14 |
15 | `); 16 | 17 | expect(vm.$el.querySelector('.el-card__header')).to.property('textContent').to.include('二师兄叫我埋梗 啦啦啦'); 18 | }); 19 | 20 | it('header', () => { 21 | vm = createTest(Card, { 22 | header: '好烦' 23 | }); 24 | 25 | expect(vm.$el.querySelector('.el-card__header')).to.property('textContent').to.include('好烦'); 26 | }); 27 | 28 | it('bodyStyle', () => { 29 | vm = createTest(Card, { 30 | bodyStyle: { padding: '10px' } 31 | }); 32 | 33 | expect(vm.$el.querySelector('.el-card__body').style.padding).to.equal('10px'); 34 | }); 35 | 36 | it('shadow', () => { 37 | vm = createTest(Card, { 38 | shadow: 'always' 39 | }); 40 | expect(vm.$el.classList.contains('is-always-shadow')).to.be.true; 41 | }); 42 | 43 | it('shadow', () => { 44 | vm = createTest(Card, { 45 | shadow: 'hover' 46 | }); 47 | expect(vm.$el.classList.contains('is-hover-shadow')).to.be.true; 48 | }); 49 | 50 | it('shadow', () => { 51 | vm = createTest(Card, { 52 | shadow: 'never' 53 | }); 54 | expect(vm.$el.classList.contains('is-never-shadow')).to.be.true; 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/reset.scss: -------------------------------------------------------------------------------- 1 | @import 'common/var'; 2 | 3 | body { 4 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; 5 | font-weight: 400; 6 | font-size: $--font-size-base; 7 | color: $--color-black; 8 | -webkit-font-smoothing: antialiased; 9 | } 10 | 11 | a { 12 | color: $--color-primary; 13 | text-decoration: none; 14 | 15 | &:hover, 16 | &:focus { 17 | color: mix($--color-white, $--color-primary, $--button-hover-tint-percent); 18 | } 19 | 20 | &:active { 21 | color: mix($--color-black, $--color-primary, $--button-active-shade-percent); 22 | } 23 | } 24 | 25 | h1, h2, h3, h4, h5, h6 { 26 | color: $--color-text-regular; 27 | font-weight: inherit; 28 | 29 | &:first-child { 30 | margin-top: 0; 31 | } 32 | 33 | &:last-child { 34 | margin-bottom: 0; 35 | } 36 | } 37 | 38 | h1 { 39 | font-size: #{$--font-size-base + 6px}; 40 | } 41 | 42 | h2 { 43 | font-size: #{$--font-size-base + 4px}; 44 | } 45 | 46 | h3 { 47 | font-size: #{$--font-size-base + 2px}; 48 | } 49 | 50 | h4, h5, h6, p { 51 | font-size: inherit; 52 | } 53 | 54 | p { 55 | line-height: 1.8; 56 | 57 | &:first-child { 58 | margin-top: 0; 59 | } 60 | 61 | &:last-child { 62 | margin-bottom: 0; 63 | } 64 | } 65 | 66 | sup, sub { 67 | font-size: #{$--font-size-base - 1px}; 68 | } 69 | 70 | small { 71 | font-size: #{$--font-size-base - 2px}; 72 | } 73 | 74 | hr { 75 | margin-top: 20px; 76 | margin-bottom: 20px; 77 | border: 0; 78 | border-top: 1px solid #eeeeee; 79 | } 80 | -------------------------------------------------------------------------------- /types/carousel.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export type CarouselIndicatorTrigger = 'hover' | 'click' 4 | export type CarouselIndicatorPosition = 'outside' | 'none' 5 | export type CarouselArrowVisibility = 'always' | 'hover' | 'never' 6 | export type CarouselType = 'card' 7 | 8 | /** Loop a series of images or texts in a limited space */ 9 | export declare class ElCarousel extends ElementUIComponent { 10 | /** Height of the carousel */ 11 | height: number 12 | 13 | /** Index of the initially active slide (starting from 0) */ 14 | initialIndex: number 15 | 16 | /** How indicators are triggered */ 17 | trigger: CarouselIndicatorTrigger 18 | 19 | /** Whether automatically loop the slides */ 20 | autoplay: boolean 21 | 22 | /** Interval of the auto loop, in milliseconds */ 23 | interval: number 24 | 25 | /** Position of the indicators */ 26 | indicatorPosition: CarouselIndicatorPosition 27 | 28 | /** When arrows are shown */ 29 | arrow: CarouselArrowVisibility 30 | 31 | /** Type of the Carousel */ 32 | type: CarouselType 33 | 34 | /** 35 | * Manually switch slide by index 36 | * 37 | * @param index Index of the slide to be switched to (starting from 0) 38 | */ 39 | setActiveItem (index: number): void 40 | 41 | /** 42 | * Manually switch slide by carousel item's name 43 | * 44 | * @param name The name of the corresponding `el-carousel-item` 45 | */ 46 | setActiveItem (name: string): void 47 | 48 | /** Switch to the previous slide */ 49 | prev (): void 50 | 51 | /** Switch to the next slide */ 52 | next (): void 53 | } 54 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.zh-CN.md: -------------------------------------------------------------------------------- 1 | # Element UI 贡献指南 2 | 3 | Hi! 首先感谢你使用 Element UI。 4 | 5 | Element UI 是一套为开发者、设计师和产品经理准备的开源组件库,旨在快速搭建页面。它基于 Vue 2.0 开发,并提供了配套的设计资源,充分满足可定制化的需求。 6 | 7 | Element UI 的成长离不开大家的支持,如果你愿意为 Element UI 贡献代码或提供建议,请阅读以下内容。 8 | 9 | ## Issue 规范 10 | - issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。如果你在使用时产生了疑问,请到 Slack 或 [Gitter](https://gitter.im/ElemeFE/element) 里咨询。 11 | 12 | - 在提交 issue 之前,请搜索相关内容是否已被提出。 13 | 14 | - 请说明 Element UI 和 Vue 的版本号,并提供操作系统和浏览器信息。推荐使用 [JSFiddle](https://jsfiddle.net/) 生成在线 demo,这能够更直观地重现问题。 15 | 16 | ## Pull Request 规范 17 | - 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。 18 | 19 | - commit 信息要以`[组件名]: 描述信息` 的形式填写,例如 `Button: fix xxx bug`。 20 | 21 | - **不要提交** `lib` 里面打包的文件。 22 | 23 | - 执行 `npm run dist` 后可以正确打包文件。 24 | 25 | - 为了兼容性以及最终打包的文件体积考虑,我们的 babel 只引入了 `preset-2015`,所以不建议使用 ES2015 的 API,例如 `Array.prototype.find`、`Object.assign`等。如果有需要,请引入第三方的 polyfill。 26 | 27 | - 提交 PR 前请 rebase,确保 commit 记录的整洁。 28 | 29 | - 确保 PR 是提交到 `dev` 分支,而不是 `master` 分支。 30 | 31 | - 如果是修复 bug,请在 PR 中给出描述信息。 32 | 33 | - 合并代码需要两名维护人员参与:一人进行 review 后 approve,另一人再次 review,通过后即可合并。 34 | 35 | ## 开发环境搭建 36 | 首先你需要 Node.js 4+,yarn 和 npm 3+。注意:我们使用 yarn 进行依赖版本的锁定,所以请不要使用 `npm install` 安装依赖。 37 | ```shell 38 | git clone git@github.com:ElemeFE/element.git 39 | npm run dev 40 | 41 | # open http://localhost:8085 42 | ``` 43 | 44 | 打包代码: 45 | 46 | ```shell 47 | npm run dist 48 | ``` 49 | 50 | ## 组件开发规范 51 | - 通过 `make new` 创建组件目录结构,包含测试代码、入口文件、文档 52 | - 如果包含父子组件,需要更改目录结构,参考 `Button` 53 | - 组件内如果依赖了其他组件,需要在当前组件内引入,参考 `Select` 54 | 55 | ## 代码规范 56 | 遵循饿了么前端的 [ESLint](https://github.com/ElemeFE/eslint-config-elemefe) 即可 57 | -------------------------------------------------------------------------------- /types/slider.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | export interface SliderTooltipFormat { 4 | /** 5 | * Format the displayed value of Slider 6 | * 7 | * @param value Value of the Slider 8 | * @returns formatted value 9 | */ 10 | (value: number): string 11 | } 12 | 13 | /** Slider Component */ 14 | export declare class ElSlider extends ElementUIComponent { 15 | /** Current value of the slider */ 16 | value: number | number[] 17 | 18 | /** Minimum value */ 19 | min: number 20 | 21 | /** Maximum value */ 22 | max: number 23 | 24 | /** Whether Slider is disabled */ 25 | disabled: boolean 26 | 27 | /** Step size */ 28 | step: number 29 | 30 | /** Whether to display an input box, works when range is false */ 31 | showInput: boolean 32 | 33 | /** Format of displayed tooltip value */ 34 | formatTooltip: SliderTooltipFormat 35 | 36 | /** Whether to display control buttons when show-input is true */ 37 | showInputControls: boolean 38 | 39 | /** Size of the input box */ 40 | inputSize: string 41 | 42 | /** Whether to display breakpoints */ 43 | showStops: boolean 44 | 45 | /** Whether to display tooltip value */ 46 | showTooltip: boolean 47 | 48 | /** Whether to select a range */ 49 | range: boolean 50 | 51 | /** Vertical mode */ 52 | vertical: boolean 53 | 54 | /** Slider height, required in vertical mode */ 55 | height: boolean 56 | 57 | /** Debounce delay when typing, in milliseconds, works when show-input is true */ 58 | debounce: number 59 | 60 | /** Custom class name for the tooltip */ 61 | tooltipClass: string 62 | } 63 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/badge.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | 4 | @include b(badge) { 5 | position: relative; 6 | vertical-align: middle; 7 | display: inline-block; 8 | 9 | @include e(content) { 10 | background-color: $--badge-fill; 11 | border-radius: $--badge-radius; 12 | color: $--color-white; 13 | display: inline-block; 14 | font-size: $--badge-font-size; 15 | height: $--badge-size; 16 | line-height: $--badge-size; 17 | padding: 0 $--badge-padding; 18 | text-align: center; 19 | white-space: nowrap; 20 | border: 1px solid $--color-white; 21 | 22 | @include when(fixed) { 23 | position: absolute; 24 | top: 0; 25 | right: #{1 + $--badge-size / 2}; 26 | transform: translateY(-50%) translateX(100%); 27 | 28 | @include when(dot) { 29 | right: 5px; 30 | } 31 | } 32 | 33 | @include when(dot) { 34 | height: 8px; 35 | width: 8px; 36 | padding: 0; 37 | right: 0; 38 | border-radius: 50%; 39 | } 40 | 41 | @each $type in (primary, success, warning, info, danger) { 42 | @include m($type) { 43 | @if $type == primary { 44 | background-color: $--color-primary; 45 | } @else if $type == success { 46 | background-color: $--color-success; 47 | } @else if $type == warning { 48 | background-color: $--color-warning; 49 | } @else if $type == info { 50 | background-color: $--color-info; 51 | } @else { 52 | background-color: $--color-danger; 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/select/src/navigation-mixin.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | hoverOption: -1 5 | }; 6 | }, 7 | 8 | computed: { 9 | optionsAllDisabled() { 10 | return this.options.filter(option => option.visible).every(option => option.disabled); 11 | } 12 | }, 13 | 14 | watch: { 15 | hoverIndex(val) { 16 | if (typeof val === 'number' && val > -1) { 17 | this.hoverOption = this.options[val] || {}; 18 | } 19 | this.options.forEach(option => { 20 | option.hover = this.hoverOption === option; 21 | }); 22 | } 23 | }, 24 | 25 | methods: { 26 | navigateOptions(direction) { 27 | if (!this.visible) { 28 | this.visible = true; 29 | return; 30 | } 31 | if (this.options.length === 0 || this.filteredOptionsCount === 0) return; 32 | if (!this.optionsAllDisabled) { 33 | if (direction === 'next') { 34 | this.hoverIndex++; 35 | if (this.hoverIndex === this.options.length) { 36 | this.hoverIndex = 0; 37 | } 38 | } else if (direction === 'prev') { 39 | this.hoverIndex--; 40 | if (this.hoverIndex < 0) { 41 | this.hoverIndex = this.options.length - 1; 42 | } 43 | } 44 | const option = this.options[this.hoverIndex]; 45 | if (option.disabled === true || 46 | option.groupDisabled === true || 47 | !option.visible) { 48 | this.navigateOptions(direction); 49 | } 50 | this.$nextTick(() => this.scrollToOption(this.hoverOption)); 51 | } 52 | } 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /types/rate.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent } from './component' 2 | 3 | /** Rate Component */ 4 | export declare class ElRate extends ElementUIComponent { 5 | /** Max rating score */ 6 | max: number 7 | 8 | /** Whether Rate is read-only */ 9 | disabled: boolean 10 | 11 | /** Whether picking half start is allowed */ 12 | allowHalf: boolean 13 | 14 | /** Threshold value between low and medium level. The value itself will be included in low level */ 15 | lowThreshold: number 16 | 17 | /** Threshold value between medium and high level. The value itself will be included in high level */ 18 | highThreshold: number 19 | 20 | /** Color array for icons. It should have 3 elements, each of which corresponds with a score level */ 21 | colors: string[] 22 | 23 | /** Color of unselected icons */ 24 | voidColor: string 25 | 26 | /** Color of unselected read-only icons */ 27 | disabledVoidColor: string 28 | 29 | /** Array of class names of icons. It should have 3 elements, each of which corresponds with a score level */ 30 | iconClasses: string[] 31 | 32 | /** Class name of unselected icons */ 33 | voidIconClass: string 34 | 35 | /** Class name of unselected read-only icons */ 36 | disabledVoidIconClass: string 37 | 38 | /** Whether to display texts */ 39 | showText: boolean 40 | 41 | /** Whether to display current score. show-score and show-text cannot be true at the same time */ 42 | showScore: boolean 43 | 44 | /** Color of texts */ 45 | textColor: string 46 | 47 | /** Text array */ 48 | texts: string[] 49 | 50 | /** Text template when the component is read-only */ 51 | scoreTemplate: string 52 | } 53 | -------------------------------------------------------------------------------- /src/mixins/migrating.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Show migrating guide in browser console. 3 | * 4 | * Usage: 5 | * import Migrating from 'element-ui/src/mixins/migrating'; 6 | * 7 | * mixins: [Migrating] 8 | * 9 | * add getMigratingConfig method for your component. 10 | * getMigratingConfig() { 11 | * return { 12 | * props: { 13 | * 'allow-no-selection': 'allow-no-selection is removed.', 14 | * 'selection-mode': 'selection-mode is removed.' 15 | * }, 16 | * events: { 17 | * selectionchange: 'selectionchange is renamed to selection-change.' 18 | * } 19 | * }; 20 | * }, 21 | */ 22 | export default { 23 | mounted() { 24 | if (process.env.NODE_ENV === 'production') return; 25 | if (!this.$vnode) return; 26 | const { props = {}, events = {} } = this.getMigratingConfig(); 27 | const { data, componentOptions } = this.$vnode; 28 | const definedProps = data.attrs || {}; 29 | const definedEvents = componentOptions.listeners || {}; 30 | 31 | for (let propName in definedProps) { 32 | if (definedProps.hasOwnProperty(propName) && props[propName]) { 33 | console.warn(`[Element Migrating][${this.$options.name}][Attribute]: ${props[propName]}`); 34 | } 35 | } 36 | 37 | for (let eventName in definedEvents) { 38 | if (definedEvents.hasOwnProperty(eventName) && events[eventName]) { 39 | console.warn(`[Element Migrating][${this.$options.name}][Event]: ${events[eventName]}`); 40 | } 41 | } 42 | }, 43 | methods: { 44 | getMigratingConfig() { 45 | return { 46 | props: {}, 47 | events: {} 48 | }; 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /types/cascader.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize } from './component' 2 | 3 | /** Trigger mode of expanding current item */ 4 | export type ExpandTrigger = 'click' | 'hover' 5 | 6 | /** Cascader Option */ 7 | export interface CascaderOption { 8 | label: string, 9 | value: any, 10 | children: CascaderOption[], 11 | disabled: boolean 12 | } 13 | 14 | /** Cascader Component */ 15 | export declare class ElCascader extends ElementUIComponent { 16 | /** Data of the options */ 17 | options: CascaderOption[] 18 | 19 | /** Configuration options */ 20 | props: object 21 | 22 | /** Selected value */ 23 | value: any[] 24 | 25 | /** Custom class name for Cascader's dropdown */ 26 | popperClass: string 27 | 28 | /** Input placeholder */ 29 | placeholder: string 30 | 31 | /** Whether Cascader is disabled */ 32 | disabled: boolean 33 | 34 | /** Whether selected value can be cleared */ 35 | clearable: boolean 36 | 37 | /** Trigger mode of expanding current item */ 38 | expandTrigger: ExpandTrigger 39 | 40 | /** Whether to display all levels of the selected value in the input */ 41 | showAllLevels: boolean 42 | 43 | /** Whether the options can be searched */ 44 | filterable: boolean 45 | 46 | /** Debounce delay when typing filter keyword, in millisecond */ 47 | debounce: number 48 | 49 | /** Whether selecting an option of any level is permitted */ 50 | changeOnSelect: boolean 51 | 52 | /** Size of Input */ 53 | size: ElementUIComponentSize 54 | 55 | /** Hook function before filtering with the value to be filtered as its parameter */ 56 | beforeFilter: (value: string) => boolean | Promise 57 | } 58 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/select-dropdown.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | @import "./popper"; 4 | 5 | @include b(select-dropdown) { 6 | position: absolute; 7 | z-index: #{$--index-top + 1}; 8 | border: $--select-dropdown-border; 9 | border-radius: $--border-radius-base; 10 | background-color: $--select-dropdown-background; 11 | box-shadow: $--select-dropdown-shadow; 12 | box-sizing: border-box; 13 | margin: 5px 0; 14 | 15 | @include when(multiple) { 16 | & .el-select-dropdown__item.selected { 17 | color: $--select-option-selected; 18 | background-color: $--select-dropdown-background; 19 | 20 | &.hover { 21 | background-color: $--select-option-hover-background; 22 | } 23 | 24 | &::after { 25 | position: absolute; 26 | right: 20px; 27 | font-family: 'element-icons'; 28 | content: "\E611"; 29 | font-size: 12px; 30 | font-weight: bold; 31 | -webkit-font-smoothing: antialiased; 32 | -moz-osx-font-smoothing: grayscale; 33 | } 34 | } 35 | } 36 | 37 | .el-scrollbar.is-empty .el-select-dropdown__list{ 38 | padding: 0; 39 | } 40 | } 41 | 42 | @include b(select-dropdown__empty) { 43 | padding: $--select-dropdown-empty-padding; 44 | margin: 0; 45 | text-align: center; 46 | color: $--select-dropdown-empty-color; 47 | font-size: $--select-font-size; 48 | } 49 | 50 | @include b(select-dropdown__wrap) { 51 | max-height: $--select-dropdown-max-height; 52 | } 53 | 54 | @include b(select-dropdown__list) { 55 | list-style: none; 56 | padding: $--select-dropdown-padding; 57 | margin: 0; 58 | box-sizing: border-box; 59 | } 60 | -------------------------------------------------------------------------------- /types/time-picker.d.ts: -------------------------------------------------------------------------------- 1 | import { ElementUIComponent, ElementUIComponentSize, ElementUIHorizontalAlignment } from './component' 2 | 3 | export interface TimePickerOptions { 4 | /** 5 | * Available time range. 6 | * e.g. `'18:30:00 - 20:30:00'` 7 | * or `['09:30:00 - 12:00:00', '14:30:00 - 18:30:00']` 8 | */ 9 | selectableRange?: string | string[], 10 | 11 | /** Format of the picker */ 12 | format?: string 13 | } 14 | 15 | /** TimePicker Component */ 16 | export declare class ElTimePicker extends ElementUIComponent { 17 | /** Whether DatePicker is read only */ 18 | readonly: boolean 19 | 20 | /** Whether DatePicker is disabled */ 21 | disabled: boolean 22 | 23 | /** Whether the input is editable */ 24 | editable: boolean 25 | 26 | /** Whether to show clear button */ 27 | clearable: boolean 28 | 29 | /** Size of Input */ 30 | size: ElementUIComponentSize 31 | 32 | /** Placeholder */ 33 | placeholder: string 34 | 35 | /** Placeholder for the start time in range mode */ 36 | startPlaceholder: string 37 | 38 | /** Placeholder for the end time in range mode */ 39 | endPlaceholder: string 40 | 41 | /** Whether to pick a time range */ 42 | isRange: boolean 43 | 44 | /** Value of the picker */ 45 | value: string | Date 46 | 47 | /** Alignment */ 48 | align: ElementUIHorizontalAlignment 49 | 50 | /** Custom class name for TimePicker's dropdown */ 51 | popperClass: string 52 | 53 | /** Additional options, check the table below */ 54 | pickerOptions: TimePickerOptions 55 | 56 | /** Range separator */ 57 | rangeSeparator: string 58 | 59 | /** 60 | * Focus the Input component 61 | */ 62 | focus (): void 63 | } 64 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/collapse.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "common/var"; 3 | @import "common/transition"; 4 | 5 | @include b(collapse) { 6 | border-top: 1px solid $--collapse-border-color; 7 | border-bottom: 1px solid $--collapse-border-color; 8 | } 9 | @include b(collapse-item) { 10 | @include e(header) { 11 | display: flex; 12 | align-items: center; 13 | height: $--collapse-header-height; 14 | line-height: $--collapse-header-height; 15 | background-color: $--collapse-header-fill; 16 | color: $--collapse-header-color; 17 | cursor: pointer; 18 | border-bottom: 1px solid $--collapse-border-color; 19 | font-size: $--collapse-header-size; 20 | font-weight: 500; 21 | transition: border-bottom-color .3s; 22 | outline: none; 23 | @include e(arrow) { 24 | margin: 0 8px 0 auto; 25 | transition: transform .3s; 26 | font-weight: 300; 27 | @include when(active) { 28 | transform: rotate(90deg); 29 | } 30 | } 31 | &.focusing:focus:not(:hover){ 32 | color: $--color-primary; 33 | } 34 | @include when(active) { 35 | border-bottom-color: transparent; 36 | } 37 | } 38 | 39 | @include e(wrap) { 40 | will-change: height; 41 | background-color: $--collapse-content-fill; 42 | overflow: hidden; 43 | box-sizing: border-box; 44 | border-bottom: 1px solid $--collapse-border-color; 45 | } 46 | 47 | @include e(content) { 48 | padding-bottom: 25px; 49 | font-size: $--collapse-content-size; 50 | color: $--collapse-content-color; 51 | line-height: 1.769230769230769; 52 | } 53 | 54 | &:last-child { 55 | margin-bottom: -1px; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/docs/zh-CN/breadcrumb.md: -------------------------------------------------------------------------------- 1 | ## Breadcrumb 面包屑 2 | 显示当前页面的路径,快速返回之前的任意页面。 3 | 4 | ### 基础用法 5 | 6 | 适用广泛的基础用法。 7 | 8 | :::demo 在`el-breadcrumb`中使用`el-breadcrumb-item`标签表示从首页开始的每一级。Element 提供了一个`separator`属性,在`el-breadcrumb`标签中设置它来决定分隔符,它只能是字符串,默认为斜杠`/`。 9 | 10 | ```html 11 | 12 | 首页 13 | 活动管理 14 | 活动列表 15 | 活动详情 16 | 17 | ``` 18 | ::: 19 | 20 | ### 图标分隔符 21 | 22 | :::demo 通过设置 `separator-class` 可使用相应的 `iconfont` 作为分隔符,注意这将使 `separator` 设置失效 23 | 24 | ```html 25 | 26 | 首页 27 | 活动管理 28 | 活动列表 29 | 活动详情 30 | 31 | ``` 32 | ::: 33 | 34 | ### Breadcrumb Attributes 35 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 36 | |---------- |-------------- |---------- |-------------------------------- |-------- | 37 | | separator | 分隔符 | string | — | 斜杠'/' | 38 | | separator-class | 图标分隔符 class | string | — | - | 39 | 40 | ### Breadcrumb Item Attributes 41 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 42 | |---------- |-------------- |---------- |-------------------------------- |-------- | 43 | | to | 路由跳转对象,同 `vue-router` 的 `to` | string/object | — | — | 44 | | replace | 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录 | boolean | — | false | 45 | -------------------------------------------------------------------------------- /types/dialog.d.ts: -------------------------------------------------------------------------------- 1 | import { VNode } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export interface DialogSlots { 5 | /** Content of the Dialog */ 6 | default: VNode[], 7 | 8 | /** Content of the Dialog title */ 9 | title: VNode[], 10 | 11 | /** Content of the Dialog footer */ 12 | footer: VNode[], 13 | 14 | [key: string]: VNode[] 15 | } 16 | 17 | /** Informs users while preserving the current page state */ 18 | export declare class ElDialog extends ElementUIComponent { 19 | /** Title of Dialog */ 20 | title: string 21 | 22 | /** Width of Dialog */ 23 | width: string 24 | 25 | /** Whether the Dialog takes up full screen */ 26 | fullscreen: boolean 27 | 28 | /** Value for margin-top of Dialog CSS */ 29 | top: string 30 | 31 | /** Whether a mask is displayed */ 32 | modal: boolean 33 | 34 | /** Whether to append modal to body element. If false, the modal will be appended to Dialog's parent element */ 35 | modalAppendToBody: boolean 36 | 37 | /** Whether scroll of body is disabled while Dialog is displayed */ 38 | lockScroll: boolean 39 | 40 | /** Custom class names for Dialog */ 41 | customClass: string 42 | 43 | /** Whether the Dialog can be closed by clicking the mask */ 44 | closeOnClickModal: boolean 45 | 46 | /** Whether the Dialog can be closed by pressing ESC */ 47 | closeOnPressEscape: boolean 48 | 49 | /** Whether to show a close button */ 50 | showClose: boolean 51 | 52 | /** Callback before Dialog closes, and it will prevent Dialog from closing */ 53 | beforeClose: (done: Function) => void 54 | 55 | /** Whether to align the header and footer in center */ 56 | center: boolean 57 | 58 | $slots: DialogSlots 59 | } 60 | -------------------------------------------------------------------------------- /src/utils/menu/aria-submenu.js: -------------------------------------------------------------------------------- 1 | import Utils from '../aria-utils'; 2 | 3 | const SubMenu = function(parent, domNode) { 4 | this.domNode = domNode; 5 | this.parent = parent; 6 | this.subMenuItems = []; 7 | this.subIndex = 0; 8 | this.init(); 9 | }; 10 | 11 | SubMenu.prototype.init = function() { 12 | this.subMenuItems = this.domNode.querySelectorAll('li'); 13 | this.addListeners(); 14 | }; 15 | 16 | SubMenu.prototype.gotoSubIndex = function(idx) { 17 | if (idx === this.subMenuItems.length) { 18 | idx = 0; 19 | } else if (idx < 0) { 20 | idx = this.subMenuItems.length - 1; 21 | } 22 | this.subMenuItems[idx].focus(); 23 | this.subIndex = idx; 24 | }; 25 | 26 | SubMenu.prototype.addListeners = function() { 27 | const keys = Utils.keys; 28 | const parentNode = this.parent.domNode; 29 | Array.prototype.forEach.call(this.subMenuItems, el => { 30 | el.addEventListener('keydown', event => { 31 | let prevDef = false; 32 | switch (event.keyCode) { 33 | case keys.down: 34 | this.gotoSubIndex(this.subIndex + 1); 35 | prevDef = true; 36 | break; 37 | case keys.up: 38 | this.gotoSubIndex(this.subIndex - 1); 39 | prevDef = true; 40 | break; 41 | case keys.tab: 42 | Utils.triggerEvent(parentNode, 'mouseleave'); 43 | break; 44 | case keys.enter: 45 | case keys.space: 46 | prevDef = true; 47 | event.currentTarget.click(); 48 | break; 49 | } 50 | if (prevDef) { 51 | event.preventDefault(); 52 | event.stopPropagation(); 53 | } 54 | return false; 55 | }); 56 | }); 57 | }; 58 | 59 | export default SubMenu; 60 | -------------------------------------------------------------------------------- /examples/index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Element 9 | 10 | 11 | 16 |
<% if (process.env.NODE_ENV === 'production') { %> 17 | 18 | <% } %> 19 | 20 | <% if (process.env.NODE_ENV === 'production') { %><% } %> 34 | 35 | -------------------------------------------------------------------------------- /test/unit/specs/alert.spec.js: -------------------------------------------------------------------------------- 1 | import { createTest, createVue, destroyVM } from '../util'; 2 | import Alert from 'packages/alert'; 3 | 4 | describe('Alert', () => { 5 | let vm; 6 | afterEach(() => { 7 | destroyVM(vm); 8 | }); 9 | 10 | it('create', () => { 11 | vm = createTest(Alert, { 12 | title: 'test', 13 | showIcon: true 14 | }, true); 15 | expect(vm.$el.querySelector('.el-alert__title').textContent).to.equal('test'); 16 | expect(vm.$el.classList.contains('el-alert--info')).to.true; 17 | }); 18 | 19 | it('type', () => { 20 | vm = createTest(Alert, { 21 | title: 'test', 22 | type: 'success', 23 | showIcon: true 24 | }, true); 25 | expect(vm.$el.classList.contains('el-alert--success')).to.true; 26 | }); 27 | 28 | it('description', () => { 29 | vm = createTest(Alert, { 30 | title: 'Dorne', 31 | description: 'Unbowed, Unbent, Unbroken', 32 | showIcon: true 33 | }, true); 34 | expect(vm.$el.querySelector('.el-alert__description').textContent) 35 | .to.equal('Unbowed, Unbent, Unbroken'); 36 | }); 37 | 38 | it('title slot', () => { 39 | vm = createVue(` 40 | 41 | foo 42 | 43 | `); 44 | 45 | expect(vm.$el.querySelector('.el-alert__title').textContent).to.equal('foo'); 46 | }); 47 | 48 | it('close', () => { 49 | vm = createVue({ 50 | template: ` 51 |
52 | 55 |
56 | ` 57 | }, true); 58 | vm.$el.querySelector('.el-alert__closebtn').click(); 59 | expect(vm.$children[0].visible).to.false; 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /packages/select/src/select-dropdown.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 75 | -------------------------------------------------------------------------------- /packages/steps/README.md: -------------------------------------------------------------------------------- 1 | # element-steps 2 | > A element-steps component for Vue.js. 3 | 4 | ## Demo 5 | http://element-component.github.io/element-steps 6 | 7 | ## Installation 8 | ```shell 9 | npm i element-steps -D 10 | ``` 11 | 12 | ## Usage 13 | ```javascript 14 | import Vue from 'vue' 15 | import ElStep from 'element-steps' 16 | import 'element-theme-chalk/dist/step.css' 17 | 18 | Vue.use(ElStep) 19 | ``` 20 | 21 | or 22 | 23 | ```javascript 24 | import Vue from 'vue' 25 | import { ElSteps, ElStep } from 'element-steps' 26 | 27 | Vue.component('el-steps', ElSteps) 28 | Vue.component('el-step', ElStep) 29 | ``` 30 | 31 | ### Steps Attributes 32 | 33 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 34 | |---------- |-------- |---------- |------------- |-------- | 35 | | space | 每个 step 的间距,不填写将自适应间距 | Number | — | — | 36 | | direction | 显示方向 | string | vertical/horizontal | horizontal | 37 | | active | 设置当前激活步骤 | number | — | 0 | 38 | | process-status | 设置当前步骤的状态 | string | wait/process/finish/error/success | process | 39 | | finish-status | 设置结束步骤的状态 | string | wait/process/finish/error/success | finish | 40 | | align-center | 标题描述居中对齐 | boolean | - | false | 41 | 42 | ### Step Attributes 43 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 44 | |---------- |-------- |---------- |------------- |-------- | 45 | | title | 标题 | string | — | — | 46 | | description | 描述性文字 | string | — | — | 47 | | icon | 图标 | Element Icon 提供的图标,如果要使用自定义图标可以通过 slot 方式写入 | string | — | 48 | 49 | ### Step Slot 50 | | name | 说明 | 51 | |----|----| 52 | | icon | 图标 | 53 | | title | 标题 | 54 | | description | 描述性文字 | 55 | 56 | 57 | ## Development 58 | ```shell 59 | make dev 60 | 61 | ## test 62 | make test 63 | 64 | ## build 65 | make build 66 | ``` 67 | 68 | # License 69 | [MIT](https://opensource.org/licenses/MIT) 70 | -------------------------------------------------------------------------------- /packages/color-picker/src/components/predefine.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /types/popover.d.ts: -------------------------------------------------------------------------------- 1 | import { VNode, VNodeDirective } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export type PopoverTrigger = 'click' | 'focus' | 'hover' | 'manual' 5 | export type PopoverPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end' 6 | 7 | export interface PopoverSlots { 8 | /** Content of popover */ 9 | default: VNode[], 10 | 11 | /** HTML element that triggers popover */ 12 | reference: VNode[] 13 | 14 | [key: string]: VNode[] 15 | } 16 | 17 | /** Popover directive definition */ 18 | export interface ElPopoverDirective extends VNodeDirective { 19 | name: 'popover', 20 | arg: string 21 | } 22 | 23 | /** Popover Component */ 24 | export declare class ElPopover extends ElementUIComponent { 25 | /** How the popover is triggered */ 26 | trigger: PopoverTrigger 27 | 28 | /** Popover title */ 29 | title: string 30 | 31 | /** Popover content, can be replaced with a default slot */ 32 | content: string 33 | 34 | /** Popover width */ 35 | width: string | number 36 | 37 | /** Popover placement */ 38 | placement: PopoverPlacement 39 | 40 | /** Whether Popover is disabled */ 41 | disabled: boolean 42 | 43 | /** Whether popover is visible */ 44 | value: boolean 45 | 46 | /** Popover offset */ 47 | offset: number 48 | 49 | /** Popover transition animation */ 50 | transition: string 51 | 52 | /** Whether a tooltip arrow is displayed or not. For more info, please refer to Vue-popper */ 53 | visibleArrow: boolean 54 | 55 | /** Parameters for popper.js */ 56 | popperOptions: object 57 | 58 | /** Custom class name for popover */ 59 | popperClass: string 60 | 61 | /** Delay of appearance when trigger is hover, in milliseconds */ 62 | openDelay: number 63 | 64 | $slots: PopoverSlots 65 | } 66 | -------------------------------------------------------------------------------- /packages/collapse/src/collapse.vue: -------------------------------------------------------------------------------- 1 | 6 | 74 | -------------------------------------------------------------------------------- /packages/col/src/col.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'ElCol', 3 | 4 | props: { 5 | span: { 6 | type: Number, 7 | default: 24 8 | }, 9 | tag: { 10 | type: String, 11 | default: 'div' 12 | }, 13 | offset: Number, 14 | pull: Number, 15 | push: Number, 16 | xs: [Number, Object], 17 | sm: [Number, Object], 18 | md: [Number, Object], 19 | lg: [Number, Object], 20 | xl: [Number, Object] 21 | }, 22 | 23 | computed: { 24 | gutter() { 25 | let parent = this.$parent; 26 | while (parent && parent.$options.componentName !== 'ElRow') { 27 | parent = parent.$parent; 28 | } 29 | return parent ? parent.gutter : 0; 30 | } 31 | }, 32 | render(h) { 33 | let classList = []; 34 | let style = {}; 35 | 36 | if (this.gutter) { 37 | style.paddingLeft = this.gutter / 2 + 'px'; 38 | style.paddingRight = style.paddingLeft; 39 | } 40 | 41 | ['span', 'offset', 'pull', 'push'].forEach(prop => { 42 | if (this[prop] || this[prop] === 0) { 43 | classList.push( 44 | prop !== 'span' 45 | ? `el-col-${prop}-${this[prop]}` 46 | : `el-col-${this[prop]}` 47 | ); 48 | } 49 | }); 50 | 51 | ['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => { 52 | if (typeof this[size] === 'number') { 53 | classList.push(`el-col-${size}-${this[size]}`); 54 | } else if (typeof this[size] === 'object') { 55 | let props = this[size]; 56 | Object.keys(props).forEach(prop => { 57 | classList.push( 58 | prop !== 'span' 59 | ? `el-col-${size}-${prop}-${props[prop]}` 60 | : `el-col-${size}-${props[prop]}` 61 | ); 62 | }); 63 | } 64 | }); 65 | 66 | return h(this.tag, { 67 | class: ['el-col', classList], 68 | style 69 | }, this.$slots.default); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/autocomplete.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/mixins"; 2 | @import "mixins/utils"; 3 | @import "common/var"; 4 | @import "./input.scss"; 5 | @import "./scrollbar.scss"; 6 | @import "./popper"; 7 | 8 | @include b(autocomplete) { 9 | position: relative; 10 | display: inline-block; 11 | } 12 | 13 | @include b(autocomplete-suggestion) { 14 | margin: 5px 0; 15 | box-shadow: $--box-shadow-light; 16 | border-radius: $--border-radius-base; 17 | border: 1px solid $--border-color-light; 18 | overflow: hidden; 19 | box-sizing: border-box; 20 | 21 | @include e(wrap) { 22 | max-height: 280px; 23 | padding: 10px 0; 24 | box-sizing: border-box; 25 | overflow: auto; 26 | background-color: $--color-white; 27 | } 28 | 29 | @include e(list) { 30 | margin: 0; 31 | padding: 0; 32 | } 33 | 34 | & li { 35 | padding: 0 20px; 36 | margin: 0; 37 | line-height: 34px; 38 | cursor: pointer; 39 | color: $--color-text-regular; 40 | font-size: $--font-size-base; 41 | list-style: none; 42 | white-space: nowrap; 43 | overflow: hidden; 44 | text-overflow: ellipsis; 45 | 46 | &:hover { 47 | background-color: $--select-option-hover-background; 48 | } 49 | 50 | &.highlighted { 51 | background-color: $--select-option-hover-background; 52 | } 53 | 54 | &.divider { 55 | margin-top: 6px; 56 | border-top: 1px solid $--color-black; 57 | } 58 | 59 | &.divider:last-child { 60 | margin-bottom: -6px; 61 | } 62 | } 63 | 64 | @include when(loading) { 65 | li { 66 | text-align: center; 67 | height: 100px; 68 | line-height: 100px; 69 | font-size: 20px; 70 | color: #999; 71 | @include utils-vertical-center; 72 | 73 | &:hover { 74 | background-color: $--color-white; 75 | } 76 | } 77 | 78 | & .el-icon-loading { 79 | vertical-align: middle; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /examples/assets/images/duohui.svg: -------------------------------------------------------------------------------- 1 | 2 | duohui-element 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/button/src/button.vue: -------------------------------------------------------------------------------- 1 | 25 | 79 | -------------------------------------------------------------------------------- /packages/tabs/src/tab-bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 58 | -------------------------------------------------------------------------------- /types/transfer.d.ts: -------------------------------------------------------------------------------- 1 | import { CreateElement, VNode } from 'vue' 2 | import { ElementUIComponent } from './component' 3 | 4 | export type TransferPanelPosition = 'left' | 'right' 5 | 6 | export interface TransferData { 7 | key: any, 8 | label: string, 9 | disabled: boolean 10 | } 11 | 12 | export interface TransferFormat { 13 | noChecked: string, 14 | hasChecked: string, 15 | } 16 | 17 | export interface TransferProps { 18 | key: string, 19 | label: string, 20 | disabled: string 21 | } 22 | 23 | export interface TransferRenderContent { 24 | /** 25 | * Render function for a specific option 26 | * 27 | * @param h The render function 28 | * @param option The option data object 29 | */ 30 | (h: CreateElement, option: TransferData): VNode 31 | } 32 | 33 | /** Transfer Component */ 34 | export declare class ElTransfer extends ElementUIComponent { 35 | /** Data source */ 36 | data: TransferData[] 37 | 38 | /** Whether Transfer is filterable */ 39 | filterable: boolean 40 | 41 | /** Placeholder for the filter input */ 42 | filterPlaceholder: string 43 | 44 | /** Custom filter method */ 45 | filterMethod: (query: string, item: TransferData) => boolean 46 | 47 | /** Order strategy for elements in the target list */ 48 | targetOrder: string 49 | 50 | /** Custom list titles */ 51 | titles: string[] 52 | 53 | /** Custom button texts */ 54 | buttonTexts: string[] 55 | 56 | /** Custom render function for data items */ 57 | renderContent: TransferRenderContent 58 | 59 | /** Texts for checking status in list header */ 60 | format: TransferFormat 61 | 62 | /** Prop aliases for data source */ 63 | props: TransferProps 64 | 65 | /** Key array of initially checked data items of the left list */ 66 | leftDefaultChecked: any[] 67 | 68 | /** Key array of initially checked data items of the right list */ 69 | rightDefaultChecked: any[] 70 | 71 | /** Clear the query text in specified panel */ 72 | clearQuery (which: TransferPanelPosition): void 73 | } 74 | -------------------------------------------------------------------------------- /packages/theme-chalk/src/date-picker/time-picker.scss: -------------------------------------------------------------------------------- 1 | @import "../common/var"; 2 | 3 | @include b(time-panel) { 4 | margin: 5px 0; 5 | border: solid 1px $--datepicker-border-color; 6 | background-color: $--color-white; 7 | box-shadow: $--box-shadow-light; 8 | border-radius: 2px; 9 | position: absolute; 10 | width: 180px; 11 | left: 0; 12 | z-index: $--index-top; 13 | user-select: none; 14 | 15 | @include e(content) { 16 | font-size: 0; 17 | position: relative; 18 | overflow: hidden; 19 | 20 | &::after, &::before { 21 | content: ""; 22 | top: 50%; 23 | position: absolute; 24 | margin-top: -15px; 25 | height: 32px; 26 | z-index: -1; 27 | left: 0; 28 | right: 0; 29 | box-sizing: border-box; 30 | padding-top: 6px; 31 | text-align: left; 32 | border-top: 1px solid $--border-color-light; 33 | border-bottom: 1px solid $--border-color-light; 34 | } 35 | 36 | &::after { 37 | left: 50%; 38 | margin-left: 12%; 39 | margin-right: 12%; 40 | } 41 | 42 | &::before { 43 | padding-left: 50%; 44 | margin-right: 12%; 45 | margin-left: 12%; 46 | } 47 | 48 | &.has-seconds { 49 | &::after { 50 | left: calc(100% / 3 * 2); 51 | } 52 | 53 | &::before { 54 | padding-left: calc(100% / 3); 55 | } 56 | } 57 | } 58 | 59 | @include e(footer) { 60 | border-top: 1px solid $--datepicker-inner-border-color; 61 | padding: 4px; 62 | height: 36px; 63 | line-height: 25px; 64 | text-align: right; 65 | box-sizing: border-box; 66 | } 67 | 68 | @include e(btn) { 69 | border: none; 70 | line-height: 28px; 71 | padding: 0 5px; 72 | margin: 0 5px; 73 | cursor: pointer; 74 | background-color: transparent; 75 | outline: none; 76 | font-size: 12px; 77 | color: $--color-text-primary; 78 | 79 | &.confirm { 80 | font-weight: 800; 81 | color: $--datepicker-active-color; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/message/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Main from './main.vue'; 3 | import { PopupManager } from 'element-ui/src/utils/popup'; 4 | import { isVNode } from 'element-ui/src/utils/vdom'; 5 | let MessageConstructor = Vue.extend(Main); 6 | 7 | let instance; 8 | let instances = []; 9 | let seed = 1; 10 | 11 | const Message = function(options) { 12 | if (Vue.prototype.$isServer) return; 13 | options = options || {}; 14 | if (typeof options === 'string') { 15 | options = { 16 | message: options 17 | }; 18 | } 19 | let userOnClose = options.onClose; 20 | let id = 'message_' + seed++; 21 | 22 | options.onClose = function() { 23 | Message.close(id, userOnClose); 24 | }; 25 | instance = new MessageConstructor({ 26 | data: options 27 | }); 28 | instance.id = id; 29 | if (isVNode(instance.message)) { 30 | instance.$slots.default = [instance.message]; 31 | instance.message = null; 32 | } 33 | instance.vm = instance.$mount(); 34 | document.body.appendChild(instance.vm.$el); 35 | instance.vm.visible = true; 36 | instance.dom = instance.vm.$el; 37 | instance.dom.style.zIndex = PopupManager.nextZIndex(); 38 | instances.push(instance); 39 | return instance.vm; 40 | }; 41 | 42 | ['success', 'warning', 'info', 'error'].forEach(type => { 43 | Message[type] = options => { 44 | if (typeof options === 'string') { 45 | options = { 46 | message: options 47 | }; 48 | } 49 | options.type = type; 50 | return Message(options); 51 | }; 52 | }); 53 | 54 | Message.close = function(id, userOnClose) { 55 | for (let i = 0, len = instances.length; i < len; i++) { 56 | if (id === instances[i].id) { 57 | if (typeof userOnClose === 'function') { 58 | userOnClose(instances[i]); 59 | } 60 | instances.splice(i, 1); 61 | break; 62 | } 63 | } 64 | }; 65 | 66 | Message.closeAll = function() { 67 | for (let i = instances.length - 1; i >= 0; i--) { 68 | instances[i].close(); 69 | } 70 | }; 71 | 72 | export default Message; 73 | --------------------------------------------------------------------------------