Transfer: add chalk theme

This commit is contained in:
Leopoldthecoder 2017-09-13 11:12:55 +08:00 committed by 杨奕
parent 9aea008b25
commit 2df521482b
7 changed files with 131 additions and 60 deletions

View File

@ -1,7 +1,7 @@
<style>
.demo-transfer {
.transfer-footer {
margin-left: 20px;
margin-left: 15px;
padding: 6px 5px;
}
}
@ -155,7 +155,7 @@ You can search and filter data items.
You can customize list titles, button texts, render function for data items, checking status texts in list footer and list footer contents.
:::demo Use `titles`, `button-texts`, `render-content` and `footer-format` to respectively customize list titles, button texts, render function for data items, checking status texts in list footer. For list footer contents, two named slots are provided: `left-footer` and `right-footer`. Plus, if you want some items initially checked, you can use `left-default-checked` and `right-default-checked`. Finally, this example demonstrate the `change` event. Note that this demo can't run in jsfiddle because it doesn't support JSX syntax. In a real project, `render-content` will work if relevant dependencies are correctly configured.
:::demo Use `titles`, `button-texts`, `render-content` and `format` to respectively customize list titles, button texts, render function for data items, checking status texts in list header. For list footer contents, two named slots are provided: `left-footer` and `right-footer`. Plus, if you want some items initially checked, you can use `left-default-checked` and `right-default-checked`. Finally, this example demonstrate the `change` event. Note that this demo can't run in jsfiddle because it doesn't support JSX syntax. In a real project, `render-content` will work if relevant dependencies are correctly configured.
```html
<template>
<el-transfer
@ -166,7 +166,7 @@ You can customize list titles, button texts, render function for data items, che
:render-content="renderFunc"
:titles="['Source', 'Target']"
:button-texts="['To left', 'To right']"
:footer-format="{
:format="{
noChecked: '${total}',
hasChecked: '${checked}/${total}'
}"
@ -267,7 +267,7 @@ By default, Transfer looks for `key`, `label` and `disabled` in a data item. If
| titles | custom list titles | array | — | ['List 1', 'List 2'] |
| button-texts | custom button texts | array | — | [ ] |
| render-content | custom render function for data items | function(h, option) | — | — |
| footer-format | texts for checking status in list footer | object{noChecked, hasChecked} | — | { noChecked: '${total} items', hasChecked: '${checked}/${total} checked' } |
| format | texts for checking status in list header | object{noChecked, hasChecked} | — | { noChecked: '${checked}/${total}', hasChecked: '${checked}/${total}' } |
| props | prop aliases for data source | object{key, label, disabled} | — | — |
| left-default-checked | key array of initially checked data items of the left list | array | — | [ ] |
| right-default-checked | key array of initially checked data items of the right list | array | — | [ ] |

View File

@ -1,7 +1,7 @@
<style>
.demo-transfer {
.transfer-footer {
margin-left: 20px;
margin-left: 15px;
padding: 6px 5px;
}
}
@ -152,7 +152,7 @@
可以对列表标题文案、按钮文案、数据项的渲染函数、列表底部的勾选状态文案、列表底部的内容区等进行自定义。
:::demo 可以使用 `titles`、`button-texts`、`render-content` 和 `footer-format` 属性分别对列表标题文案、按钮文案、数据项的渲染函数和列表部的勾选状态文案进行自定义。对于列表底部的内容区,提供了两个具名 slot`left-footer` 和 `right-footer`。此外,如果希望某些数据项在初始化时就被勾选,可以使用 `left-default-checked``right-default-checked` 属性。最后,本例还展示了 `change` 事件的用法。注意:由于 jsfiddle 不支持 JSX 语法,所以本例在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。
:::demo 可以使用 `titles`、`button-texts`、`render-content` 和 `format` 属性分别对列表标题文案、按钮文案、数据项的渲染函数和列表部的勾选状态文案进行自定义。对于列表底部的内容区,提供了两个具名 slot`left-footer` 和 `right-footer`。此外,如果希望某些数据项在初始化时就被勾选,可以使用 `left-default-checked``right-default-checked` 属性。最后,本例还展示了 `change` 事件的用法。注意:由于 jsfiddle 不支持 JSX 语法,所以本例在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。
```html
<template>
<el-transfer
@ -163,7 +163,7 @@
:render-content="renderFunc"
:titles="['Source', 'Target']"
:button-texts="['到左边', '到右边']"
:footer-format="{
:format="{
noChecked: '${total}',
hasChecked: '${checked}/${total}'
}"
@ -264,7 +264,7 @@
| titles | 自定义列表标题 | array | — | ['列表 1', '列表 2'] |
| button-texts | 自定义按钮文案 | array | — | [ ] |
| render-content | 自定义数据项渲染函数 | function(h, option) | — | — |
| footer-format | 列表底部勾选状态文案 | object{noChecked, hasChecked} | — | { noChecked: '共 ${total} 项', hasChecked: '已选 ${checked}/${total} 项' } |
| format | 列表顶部勾选状态文案 | object{noChecked, hasChecked} | — | { noChecked: '${checked}/${total}', hasChecked: '${checked}/${total}' } |
| props | 数据源的字段别名 | object{key, label, disabled} | — | — |
| left-default-checked | 初始状态下左侧列表的已勾选项的 key 数组 | array | — | [ ] |
| right-default-checked | 初始状态下右侧列表的已勾选项的 key 数组 | array | — | [ ] |

View File

@ -48,6 +48,10 @@ $--color-text-placeholder: #b4bccc;
$--link-color: $--color-primary-light-2;
$--link-hover-color: $--color-primary;
/* Background
-------------------------- */
$--background-color-base: #f5f7fa;
/* Border
-------------------------- */
$--border-width-base: 1px;
@ -628,16 +632,16 @@ $--collapse-content-color: $--color-text-primary;
/* Transfer
--------------------------*/
$--transfer-border-color: $--color-text-regular;
$--transfer-box-shadow: $--box-shadow-base;
$--transfer-border-color: $--border-color-lighter;
$--transfer-border-radius: $--border-radius-base;
$--transfer-panel-width: 200px;
$--transfer-panel-header-height: 36px;
$--transfer-panel-header-background: $--color-text-primary;
$--transfer-panel-footer-height: 36px;
$--transfer-panel-header-height: 40px;
$--transfer-panel-header-background: $--background-color-base;
$--transfer-panel-footer-height: 40px;
$--transfer-panel-body-height: 246px;
$--transfer-item-height: 32px;
$--transfer-item-height: 30px;
$--transfer-item-hover-background: $--color-text-secondary;
$--transfer-filter-height: 22px;
$--transfer-filter-height: 32px;
/* Header
--------------------------*/

View File

@ -12,19 +12,47 @@
@include e(buttons) {
display: inline-block;
vertical-align: middle;
padding: 0 10px;
padding: 0 30px;
}
.el-button {
display: block;
margin: 0 auto;
padding: 8px 12px;
@include e(button) {
display: block;
margin: 0 auto;
padding: 10px;
border-radius: 50%;
color: $--color-white;
background-color: $--color-primary;
font-size: 0;
&:first-child {
margin-bottom: 6px;
@include when(with-texts) {
border-radius: $--border-radius-base;
}
@include when(disabled) {
border: $--border-base;
background-color: $--background-color-base;
color: $--color-text-placeholder;
&:hover {
border: $--border-base;
background-color: $--background-color-base;
color: $--color-text-placeholder;
}
}
.el-button [class*="el-icon-"] + span {
&:first-child {
margin-bottom: 10px;
}
&:nth-child(2) {
margin: 0;
}
i, span {
font-size: 14px;
}
& [class*="el-icon-"] + span {
margin-left: 0;
}
}
@ -32,8 +60,9 @@
@include b(transfer-panel) {
border: 1px solid $--transfer-border-color;
border-radius: $--transfer-border-radius;
overflow: hidden;
background: $--color-white;
box-shadow: $--transfer-box-shadow;
display: inline-block;
vertical-align: middle;
width: $--transfer-panel-width;
@ -41,8 +70,11 @@
position: relative;
@include e(body) {
padding-bottom: $--transfer-panel-footer-height;
height: $--transfer-panel-body-height;
@include when(with-footer) {
padding-bottom: $--transfer-panel-footer-height;
}
}
@include e(list) {
@ -54,14 +86,15 @@
box-sizing: border-box;
@include when(filterable) {
height: #{$--transfer-panel-body-height - $--transfer-filter-height - 10px};
height: #{$--transfer-panel-body-height - $--transfer-filter-height - 20px};
padding-top: 0;
}
}
@include e(item) {
height: $--transfer-item-height;
line-height: $--transfer-item-height;
padding-left: 20px;
padding-left: 15px;
display: block;
& + .el-transfer-panel__item {
@ -69,11 +102,11 @@
}
&.el-checkbox {
color: $--color-black;
color: $--color-text-regular;
}
&:hover {
background: $--transfer-item-hover-background;
color: $--color-primary;
}
&.el-checkbox .el-checkbox__label {
@ -81,19 +114,20 @@
@include utils-ellipsis;
display: block;
box-sizing: border-box;
padding-left: 28px;
padding-left: 24px;
}
.el-checkbox__input {
position: absolute;
top: 9px;
top: 8px;
}
}
@include e(filter) {
margin-top: 10px;
margin-top: 15px;
margin-bottom: 5px;
text-align: center;
padding: 0 10px;
padding: 0 15px;
width: 100%;
box-sizing: border-box;
@ -102,10 +136,14 @@
width: 100%;
display: inline-block;
box-sizing: border-box;
border-radius: #{$--transfer-filter-height / 2};
padding-right: 10px;
padding-left: 30px;
}
.el-input__icon {
right: 10px;
right: auto;
left: 15px;
}
.el-icon-circle-close {
@ -118,10 +156,29 @@
line-height: $--transfer-panel-header-height;
background: $--transfer-panel-header-background;
margin: 0;
padding-left: 20px;
padding-left: 15px;
border-bottom: 1px solid $--transfer-border-color;
box-sizing: border-box;
color: $--color-black;
.el-checkbox {
display: block;
line-height: 40px;
.el-checkbox__label {
font-size: 16px;
color: $--color-text-primary;
font-weight: normal;
span {
float: right;
margin-right: 15px;
color: $--color-text-secondary;
font-size: 12px;
font-weight: normal;
}
}
}
}
.el-transfer-panel__footer {
@ -139,7 +196,7 @@
.el-checkbox {
padding-left: 20px;
color: $--color-black;
color: $--color-text-regular;
}
}
@ -147,12 +204,12 @@
margin: 0;
height: $--transfer-item-height;
line-height: $--transfer-item-height;
padding: 6px 20px 0;
color: $--color-black;
padding: 6px 15px 0;
color: $--color-text-secondary;
}
.el-checkbox__label {
padding-left: 14px;
padding-left: 8px;
}
.el-checkbox__inner {

View File

@ -12,7 +12,7 @@
<div class="el-transfer__buttons">
<el-button
type="primary"
size="small"
:class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
@click.native="addToLeft"
:disabled="rightChecked.length === 0">
<i class="el-icon-arrow-left"></i>
@ -20,7 +20,7 @@
</el-button>
<el-button
type="primary"
size="small"
:class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
@click.native="addToRight"
:disabled="leftChecked.length === 0">
<span v-if="buttonTexts[1] !== undefined">{{ buttonTexts[1] }}</span>
@ -98,7 +98,7 @@
return [];
}
},
footerFormat: {
format: {
type: Object,
default() {
return {};
@ -131,6 +131,10 @@
targetData() {
return this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1);
},
hasButtonTexts() {
return this.buttonTexts.length === 2;
}
},

View File

@ -1,8 +1,16 @@
<template>
<div class="el-transfer-panel">
<p class="el-transfer-panel__header">{{ title }}</p>
<p class="el-transfer-panel__header">
<el-checkbox
v-model="allChecked"
@change="handleAllCheckedChange"
:indeterminate="isIndeterminate">
{{ title }}
<span>{{ checkedSummary }}</span>
</el-checkbox>
</p>
<div class="el-transfer-panel__body">
<div :class="['el-transfer-panel__body', hasFooter ? 'is-with-footer' : '']">
<el-input
class="el-transfer-panel__filter"
v-model="query"
@ -34,12 +42,7 @@
class="el-transfer-panel__empty"
v-show="data.length === 0 && !hasNoMatch">{{ t('el.transfer.noData') }}</p>
</div>
<p class="el-transfer-panel__footer">
<el-checkbox
v-model="allChecked"
@change="handleAllCheckedChange"
:indeterminate="isIndeterminate">{{ checkedSummary }}</el-checkbox>
<p class="el-transfer-panel__footer" v-if="hasFooter">
<slot></slot>
</p>
</div>
@ -95,7 +98,7 @@
placeholder: String,
title: String,
filterable: Boolean,
footerFormat: Object,
format: Object,
filterMethod: Function,
defaultChecked: Array,
props: Object
@ -167,15 +170,13 @@
checkedSummary() {
const checkedLength = this.checked.length;
const dataLength = this.data.length;
const { noChecked, hasChecked } = this.footerFormat;
const { noChecked, hasChecked } = this.format;
if (noChecked && hasChecked) {
return checkedLength > 0
? hasChecked.replace(/\${checked}/g, checkedLength).replace(/\${total}/g, dataLength)
: noChecked.replace(/\${total}/g, dataLength);
} else {
return checkedLength > 0
? this.t('el.transfer.hasCheckedFormat', { total: dataLength, checked: checkedLength })
: this.t('el.transfer.noCheckedFormat', { total: dataLength });
return `${ checkedLength }/${ dataLength }`;
}
},
@ -204,6 +205,10 @@
disabledProp() {
return this.props.disabled || 'disabled';
},
hasFooter() {
return !!this.$slots.default;
}
},

View File

@ -91,11 +91,11 @@ describe('Transfer', () => {
});
it('customize', () => {
vm = createTransfer('v-model="value" :titles="titles" :render-content="renderFunc" :footer-format="format"', {
vm = createTransfer('v-model="value" :titles="titles" :render-content="renderFunc" :format="format"', {
data() {
return {
value: [2],
titles: ['1', '2'],
titles: ['1', '2'],
format: { noChecked: 'no', hasChecked: 'has' },
renderFunc(h, option) {
return <span>{ option.key } - { option.label }</span>;
@ -104,9 +104,10 @@ describe('Transfer', () => {
}
});
const transfer = vm.$refs.transfer.$el;
expect(transfer.querySelector('.el-transfer-panel__header').innerText).to.equal('1');
expect(transfer.querySelector('.el-checkbox__label span').innerText).to.equal('1 - 备选项 1');
expect(transfer.querySelector('.el-transfer-panel__footer .el-checkbox__label').innerText).to.equal('no');
const label = transfer.querySelector('.el-transfer-panel__header .el-checkbox__label');
expect(label.innerText.indexOf('表1') > -1).to.true;
expect(transfer.querySelector('.el-transfer-panel__list .el-checkbox__label span').innerText).to.equal('1 - 备选项 1');
expect(label.querySelector('span').innerText).to.equal('no');
});
it('check', () => {