mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-09 04:31:35 +08:00
feat(transfer): there is still some bugs
This commit is contained in:
parent
3021ec8fa5
commit
97d16c86c2
25
README.md
25
README.md
@ -114,15 +114,16 @@ Vue.use(naiveUi)
|
||||
v0.3 cascader
|
||||
v0.4 refactor popover
|
||||
v0.5 finish all planned components
|
||||
v0.6 refactor form component
|
||||
v0.7 refactor table component
|
||||
v0.8 fulfill props for all components
|
||||
v0.9 split icons for components
|
||||
v0.10 refactor css
|
||||
v0.11 import on demand
|
||||
v0.12 i18n
|
||||
v0.13 unit test
|
||||
v0.14 light theme
|
||||
v0.15 document formation
|
||||
v0.16 code clean
|
||||
v0.17 refactor document page
|
||||
v0.6 add keyboard event on planned components
|
||||
v0.7 refactor form component
|
||||
v0.8 refactor table component
|
||||
v0.9 fulfill props for all components
|
||||
v0.10 split icons for components
|
||||
v0.11 refactor css
|
||||
v0.12 import on demand
|
||||
v0.13 i18n
|
||||
v0.14 unit test
|
||||
v0.15 light theme
|
||||
v0.16 refactor using proper html tags
|
||||
v0.17 document formation
|
||||
v0.18 refactor document page
|
||||
|
32
demo/components/transferDemo/index.vue
Normal file
32
demo/components/transferDemo/index.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div
|
||||
ref="doc"
|
||||
class="n-doc"
|
||||
>
|
||||
<div class="n-doc-header">
|
||||
<n-gradient-text :font-size="20">
|
||||
scaffold
|
||||
</n-gradient-text>
|
||||
</div>
|
||||
<div class="n-doc-body">
|
||||
<scaffold />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scaffold from './scaffold.demo.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
scaffold
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
67
demo/components/transferDemo/scaffold.demo.vue
Normal file
67
demo/components/transferDemo/scaffold.demo.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Scaffold
|
||||
</div>
|
||||
<div
|
||||
class="n-doc-section__view"
|
||||
style="flex-wrap: nowrap;"
|
||||
>
|
||||
<!--EXAMPLE_START-->
|
||||
<n-transfer
|
||||
ref="transfer"
|
||||
v-model="value"
|
||||
:options="options"
|
||||
/>
|
||||
<!--EXAMPLE_END-->
|
||||
</div>
|
||||
<div class="n-doc-section__inspect">
|
||||
<n-button @click="regenOptions">
|
||||
Regen Options
|
||||
</n-button>
|
||||
<n-button @click="regenValues">
|
||||
Regen Values
|
||||
</n-button>
|
||||
</div>
|
||||
<pre class="n-doc-section__inspect">{{ JSON.stringify(value) }}</pre>
|
||||
<pre class="n-doc-section__inspect">{{ $refs.transfer ? $refs.transfer._data : null }}</pre>
|
||||
<n-doc-source-block>
|
||||
<!--SOURCE-->
|
||||
</n-doc-source-block>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let prefix = null
|
||||
|
||||
function genOptions () {
|
||||
prefix = Math.random().toString(36).slice(2, 5)
|
||||
return Array.apply(null, { length: 20 }).map((v, i) => ({
|
||||
label: prefix + 'Option' + i,
|
||||
value: prefix + i
|
||||
}))
|
||||
}
|
||||
|
||||
function genValues () {
|
||||
return Array.apply(null, { length: 5 }).map((v, i) => prefix + i)
|
||||
}
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
options: genOptions(),
|
||||
value: genValues()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
regenOptions () {
|
||||
this.options = genOptions()
|
||||
},
|
||||
regenValues () {
|
||||
this.value = genValues()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -202,6 +202,10 @@ export default {
|
||||
{
|
||||
name: 'Tooltip',
|
||||
path: '/n-tooltip'
|
||||
},
|
||||
{
|
||||
name: 'Transfer',
|
||||
path: '/n-transfer'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -51,6 +51,7 @@ import anchorDemo from './components/anchorDemo'
|
||||
import popselectDemo from './components/popselectDemo'
|
||||
import appDemo from './components/appDemo'
|
||||
import advanceTableDemos from './components/advanceTableDemos'
|
||||
import transferDemo from './components/transferDemo'
|
||||
|
||||
import demo from './demo'
|
||||
|
||||
@ -138,7 +139,8 @@ const routes = [
|
||||
{ path: '/n-dropdown', component: dropdownDemo },
|
||||
{ path: '/n-popselect', component: popselectDemo },
|
||||
{ path: '/n-app', component: appDemo },
|
||||
{ path: '/n-cancel-mark-debug', component: cancelMarkDebug }
|
||||
{ path: '/n-cancel-mark-debug', component: cancelMarkDebug },
|
||||
{ path: '/n-transfer', component: transferDemo }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
191
demo/readme.js
191
demo/readme.js
@ -81,6 +81,12 @@ Vue.use(naiveUi)
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TimePicker</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GradientText</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;">🆗</td>
|
||||
@ -135,24 +141,6 @@ Vue.use(naiveUi)
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FormItem</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Form</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Table</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td>Function is not fulfilled</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tooltip</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
@ -178,13 +166,7 @@ Vue.use(naiveUi)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tab</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Breadcrumb</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@ -213,24 +195,12 @@ Vue.use(naiveUi)
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Statistic</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Popconfirm</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Anchor</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BackTop</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
@ -249,12 +219,6 @@ Vue.use(naiveUi)
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Card</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Collapse</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
@ -262,7 +226,13 @@ Vue.use(naiveUi)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cascader</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dropdown</td>
|
||||
<td style="text-align:center;">😍</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
@ -272,6 +242,120 @@ Vue.use(naiveUi)
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transfer</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Carousel</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Grid</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Card</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Anchor</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Statistic</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Breadcrumb</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FormItem</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Form</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Table</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;">❌</td>
|
||||
<td>Function is not fulfilled</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AutoComplete</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Slider</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TreeSelect</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transfer</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Upload</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Empty</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tree</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spin</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Drawer</td>
|
||||
<td style="text-align:center;">🚧</td>
|
||||
<td style="text-align:center;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<ol>
|
||||
@ -284,4 +368,21 @@ Vue.use(naiveUi)
|
||||
<li>Refactor documentation page(for code clairity)</li>
|
||||
<li>Code refactor for some 😢 messy code(which is my bad…)</li>
|
||||
<li>Refactor CSS use mixins(which means I should learn SCSS hard…)</li>
|
||||
</ol></div>`
|
||||
</ol>
|
||||
<h2 id="roadmap">RoadMap</h2>
|
||||
<p>v0.3 cascader
|
||||
v0.4 refactor popover
|
||||
v0.5 finish all planned components
|
||||
v0.6 add keyboard event on planned components
|
||||
v0.7 refactor form component
|
||||
v0.8 refactor table component
|
||||
v0.9 fulfill props for all components
|
||||
v0.10 split icons for components
|
||||
v0.11 refactor css
|
||||
v0.12 import on demand
|
||||
v0.13 i18n
|
||||
v0.14 unit test
|
||||
v0.15 light theme
|
||||
v0.16 refactor using proper html tags
|
||||
v0.17 document formation
|
||||
v0.18 refactor document page</p></div>`
|
||||
|
2
index.js
2
index.js
@ -51,6 +51,7 @@ import Dropdown from './packages/common/Dropdown'
|
||||
import Popselect from './packages/common/Popselect'
|
||||
import App from './packages/common/App'
|
||||
import CancelMark from './packages/base/CancelMark'
|
||||
import Transfer from './packages/common/Transfer'
|
||||
|
||||
function install (Vue) {
|
||||
Card.install(Vue)
|
||||
@ -106,6 +107,7 @@ function install (Vue) {
|
||||
Popselect.install(Vue)
|
||||
App.install(Vue)
|
||||
CancelMark.install(Vue)
|
||||
Transfer.install(Vue)
|
||||
}
|
||||
|
||||
export default {
|
||||
|
8
packages/common/Transfer/index.js
Normal file
8
packages/common/Transfer/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
/* istanbul ignore file */
|
||||
import Transfer from './src/main.vue'
|
||||
|
||||
Transfer.install = function (Vue) {
|
||||
Vue.component(Transfer.name, Transfer)
|
||||
}
|
||||
|
||||
export default Transfer
|
58
packages/common/Transfer/src/TransferListItem.vue
Normal file
58
packages/common/Transfer/src/TransferListItem.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<li
|
||||
class="n-transfer-list-item"
|
||||
@click="handleClick"
|
||||
>
|
||||
<div class="n-transfer-list-item__checkbox">
|
||||
<n-checkbox
|
||||
:value="checked"
|
||||
@input="handleInput"
|
||||
/>
|
||||
</div>
|
||||
<slot />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NCheckbox from '../../Checkbox'
|
||||
|
||||
export default {
|
||||
name: 'NTransferListItem',
|
||||
components: {
|
||||
NCheckbox
|
||||
},
|
||||
props: {
|
||||
checked: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
validator () {
|
||||
return true
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
transitionName () {
|
||||
return this.source ? 'n-transfer-list-item-source--transition' : 'n-transfer-list-item-target--transition'
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.show = true
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
this.$emit('click')
|
||||
},
|
||||
handleInput (checked) {
|
||||
this.$emit('input', checked, this.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
257
packages/common/Transfer/src/main.vue
Normal file
257
packages/common/Transfer/src/main.vue
Normal file
@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<div class="n-transfer">
|
||||
<div class="n-transfer-list">
|
||||
<div class="n-transfer-list-header">
|
||||
<div class="n-transfer-list-header__checkbox">
|
||||
<n-checkbox
|
||||
:value="sourceHeaderCheckboxChecked"
|
||||
:indeterminate="sourceHeaderCheckboxIndeterminate"
|
||||
@input="handleSourceHeaderCheckboxInput"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-transfer-list-header__header">
|
||||
Source
|
||||
</div>
|
||||
<div class="n-transfer-list-header__label">
|
||||
{{ sourceCheckedValueSet.size }} / {{ sourceOptions.length }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-transfer-list-body">
|
||||
<n-scrollbar ref="leftScrollbar">
|
||||
<ul class="n-transfer-list-body-content">
|
||||
<transition
|
||||
v-for="option in memorizedOptions"
|
||||
:key="option.value"
|
||||
name="n-transfer-list-item-source--transition"
|
||||
>
|
||||
<n-transfer-list-item
|
||||
v-if="sourceValueSet.has(option.value)"
|
||||
:value="option.value"
|
||||
:checked="sourceCheckedValueSet.has(option.value)"
|
||||
@click="handleSourceCheckboxInput(
|
||||
!sourceCheckedValueSet.has(option.value),
|
||||
option.value
|
||||
)"
|
||||
>
|
||||
{{ option.label }}
|
||||
</n-transfer-list-item>
|
||||
</transition>
|
||||
</ul>
|
||||
</n-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-transfer-actions">
|
||||
<button @click="handleToTargetClick">
|
||||
To Target
|
||||
</button>
|
||||
<button @click="handleToSourceClick">
|
||||
To Source
|
||||
</button>
|
||||
</div>
|
||||
<div class="n-transfer-list">
|
||||
<div class="n-transfer-list-header">
|
||||
<div class="n-transfer-list-header__checkbox">
|
||||
<n-checkbox
|
||||
:value="targetHeaderCheckboxChecked"
|
||||
:indeterminate="targetHeaderCheckboxIndeterminate"
|
||||
@input="handleTargetHeaderCheckboxInput"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-transfer-list-header__header">
|
||||
Target
|
||||
</div>
|
||||
<div class="n-transfer-list-header__label">
|
||||
{{ targetCheckedValueSet.size }} / {{ targetOptions.length }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-transfer-list-body">
|
||||
<n-scrollbar ref="rightScrollbar">
|
||||
<ul class="n-transfer-list-body-content">
|
||||
<transition
|
||||
v-for="option in memorizedOptions"
|
||||
:key="option.value"
|
||||
name="n-transfer-list-item-target--transition"
|
||||
>
|
||||
<n-transfer-list-item
|
||||
v-if="targetValueSet.has(option.value)"
|
||||
:value="option.value"
|
||||
:checked="targetCheckedValueSet.has(option.value)"
|
||||
@click="handleTargetCheckboxInput(
|
||||
!targetCheckedValueSet.has(option.value),
|
||||
option.value
|
||||
)"
|
||||
>
|
||||
{{ option.label }}
|
||||
</n-transfer-list-item>
|
||||
</transition>
|
||||
</ul>
|
||||
</n-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NCheckbox from '../../Checkbox'
|
||||
import NScrollbar from '../../Scrollbar'
|
||||
import NTransferListItem from './TransferListItem'
|
||||
|
||||
export default {
|
||||
name: 'NTransfer',
|
||||
components: {
|
||||
NCheckbox,
|
||||
NScrollbar,
|
||||
NTransferListItem
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: null
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
sourceCheckedValues: [],
|
||||
targetCheckedValues: [],
|
||||
memorizedOptions: null,
|
||||
init: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sourceHeaderCheckboxChecked () {
|
||||
return this.sourceCheckedValueSet.size === this.sourceOptions.length && !!this.sourceOptions.length
|
||||
},
|
||||
targetHeaderCheckboxChecked () {
|
||||
return this.targetCheckedValueSet.size === this.targetOptions.length && !!this.targetOptions.length
|
||||
},
|
||||
valueToOptionMap () {
|
||||
const map = new Map()
|
||||
this.memorizedOptions.forEach(option => {
|
||||
map.set(option.value, option)
|
||||
})
|
||||
return map
|
||||
},
|
||||
sourceHeaderCheckboxIndeterminate () {
|
||||
return this.sourceCheckedValueSet.size !== 0 && this.sourceCheckedValueSet.size < this.sourceOptions.length
|
||||
},
|
||||
targetHeaderCheckboxIndeterminate () {
|
||||
return this.targetCheckedValueSet.size !== 0 && this.targetCheckedValueSet.size < this.targetOptions.length
|
||||
},
|
||||
sourceValueSet () {
|
||||
return new Set(this.sourceOptions.map(option => option.value))
|
||||
},
|
||||
targetValueSet () {
|
||||
return new Set(this.targetOptions.map(option => option.value))
|
||||
},
|
||||
sourceCheckedValueSet () {
|
||||
return new Set(this.sourceCheckedValues.filter(value => this.valueToOptionMap.has(value)))
|
||||
},
|
||||
targetCheckedValueSet () {
|
||||
return new Set(this.targetCheckedValues.filter(value => this.valueToOptionMap.has(value)))
|
||||
},
|
||||
sourceOptions () {
|
||||
const valueSet = Array.isArray(this.value) ? new Set(this.value) : new Set()
|
||||
return this.memorizedOptions.filter(option => !valueSet.has(option.value))
|
||||
},
|
||||
targetOptions () {
|
||||
const value = Array.isArray(this.value) ? this.value : []
|
||||
return value.filter(v => this.valueToOptionMap.has(v)).map(v => this.valueToOptionMap.get(v))
|
||||
},
|
||||
orderedOptions () {
|
||||
return this.sourceOptions.concat(this.targetOptions)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options (newOptions) {
|
||||
this.init = true
|
||||
this.$nextTick().then(() => {
|
||||
this.memorizedOptions = newOptions
|
||||
this.sourceCheckedValues = []
|
||||
this.targetCheckedValues = []
|
||||
return this.$nextTick()
|
||||
}).then(() => {
|
||||
this.init = false
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick().then(() => {
|
||||
this.init = false
|
||||
})
|
||||
},
|
||||
created () {
|
||||
this.memorizedOptions = this.options
|
||||
},
|
||||
methods: {
|
||||
emitInputEvent (value) {
|
||||
this.$emit('input', this.cleanValue(value))
|
||||
},
|
||||
cleanValue (value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter((v) => this.valueToOptionMap.has(v))
|
||||
} else return null
|
||||
},
|
||||
handleSourceHeaderCheckboxInput (value) {
|
||||
if (this.sourceHeaderCheckboxIndeterminate) {
|
||||
this.sourceCheckedValues = []
|
||||
return
|
||||
}
|
||||
if (value) {
|
||||
this.sourceCheckedValues = this.sourceOptions.map(option => option.value)
|
||||
} else {
|
||||
this.sourceCheckedValues = []
|
||||
}
|
||||
},
|
||||
handleTargetHeaderCheckboxInput (value) {
|
||||
if (this.targetHeaderCheckboxIndeterminate) {
|
||||
this.targetCheckedValues = []
|
||||
return
|
||||
}
|
||||
if (value) {
|
||||
this.targetCheckedValues = this.targetOptions.map(option => option.value)
|
||||
} else {
|
||||
this.targetCheckedValues = []
|
||||
}
|
||||
},
|
||||
handleTargetCheckboxInput (checked, value) {
|
||||
if (checked) {
|
||||
this.targetCheckedValues.push(value)
|
||||
} else {
|
||||
const index = this.targetCheckedValues.findIndex(v => v === value)
|
||||
if (~index) this.targetCheckedValues.splice(index, 1)
|
||||
}
|
||||
},
|
||||
handleSourceCheckboxInput (checked, value) {
|
||||
if (checked) {
|
||||
this.sourceCheckedValues.push(value)
|
||||
} else {
|
||||
const index = this.sourceCheckedValues.findIndex(v => v === value)
|
||||
if (~index) this.sourceCheckedValues.splice(index, 1)
|
||||
}
|
||||
},
|
||||
handleToTargetClick () {
|
||||
let newValue = Array.isArray(this.value) ? this.value : []
|
||||
newValue = this.sourceCheckedValues.concat(newValue)
|
||||
this.emitInputEvent(newValue)
|
||||
this.sourceCheckedValues = []
|
||||
},
|
||||
handleToSourceClick () {
|
||||
let newValue = Array.isArray(this.value) ? this.value : []
|
||||
newValue = newValue.filter(value => this.valueToOptionMap.has(value))
|
||||
const filteredValues = newValue.filter(value => this.targetCheckedValueSet.has(value))
|
||||
const stayedValues = newValue.filter(value => !this.targetCheckedValueSet.has(value))
|
||||
newValue = stayedValues
|
||||
const reorderedOptionsFirstPart = filteredValues.concat(stayedValues).map(value => this.valueToOptionMap.get(value))
|
||||
const reorderedOptionsSecondPart = this.memorizedOptions.filter(option => !filteredValues.includes(option.value) && !stayedValues.includes(option.value))
|
||||
const reorderedOptions = reorderedOptionsFirstPart.concat(reorderedOptionsSecondPart)
|
||||
this.memorizedOptions = reorderedOptions
|
||||
this.emitInputEvent(stayedValues)
|
||||
this.targetCheckedValues = []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -169,16 +169,20 @@
|
||||
&.n-base-picker--disabled {
|
||||
cursor: not-allowed;
|
||||
.n-base-picker-label, .n-base-picker-tags {
|
||||
cursor: not-allowed;
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.n-base-picker-tag {
|
||||
cursor: not-allowed;
|
||||
border-color: rgba(255, 255, 255, 0.20);
|
||||
color: rgba(255, 255, 255, 0.20);
|
||||
}
|
||||
.n-base-picker__placeholder {
|
||||
cursor: not-allowed;
|
||||
color: rgba(255, 255, 255, 0.20);
|
||||
}
|
||||
.n-base-picker-label__input {
|
||||
cursor: not-allowed;
|
||||
color: rgba(255, 255, 255, 0.20);
|
||||
&.n-base-picker-label__input--placeholder {
|
||||
color: rgba(255, 255, 255, 0.20);
|
||||
@ -225,7 +229,7 @@
|
||||
}
|
||||
.n-base-picker-input-tag__mirror {
|
||||
position: absolute;
|
||||
padding-right: .5em;
|
||||
padding-right: 1em;
|
||||
left: 0;
|
||||
top: 0;
|
||||
white-space: pre;
|
||||
|
79
styles/Transfer.scss
Normal file
79
styles/Transfer.scss
Normal file
@ -0,0 +1,79 @@
|
||||
@import './mixins/mixins.scss';
|
||||
@import './theme/default.scss';
|
||||
|
||||
@include b(transfer) {
|
||||
display: flex;
|
||||
@include b(transfer-list) {
|
||||
width: 182px;
|
||||
height: 312px;
|
||||
background-color: rgba(75,81,106,1);
|
||||
border-radius: 6px;
|
||||
@include b(transfer-list-header) {
|
||||
background:rgba(255,255,255,0.2);
|
||||
display: flex;
|
||||
border-radius: 6px 6px 0 0;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
@include e(checkbox) {
|
||||
position: relative;
|
||||
padding: 0 8px 0 14px;
|
||||
@include b(checkbox) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@include e(header) {
|
||||
flex: 1;
|
||||
line-height: 1;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
@include m(disabled) {
|
||||
color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
}
|
||||
@include e(label) {
|
||||
font-size: 12px;
|
||||
justify-self: flex-end;
|
||||
margin-right: 14px;
|
||||
}
|
||||
}
|
||||
@include b(transfer-list-body) {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 272px;
|
||||
@include b(transfer-list-body-content) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@include b(transfer-list-item) {
|
||||
@include slide-right-transition(transfer-list-item-source, 2s);
|
||||
@include slide-left-transition(transfer-list-item-target, 2s);
|
||||
cursor: pointer;
|
||||
max-height: 34px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
height: 34px;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
@include e(checkbox) {
|
||||
position: relative;
|
||||
padding: 0 8px 0 14px;
|
||||
@include b(checkbox) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@include m(disabled) {
|
||||
color: rgba(255, 255, 255, 0.25);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
@include m(selected) {
|
||||
color: rgba(99, 226, 183, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@include b(transfer-actions) {
|
||||
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@
|
||||
@import './BaseCancelMark.scss';
|
||||
@import './BasePicker.scss';
|
||||
@import './BaseSelectMenu.scss';
|
||||
@import './Transfer.scss';
|
||||
|
||||
@import "./NimbusServiceLayout.scss";
|
||||
@import "./Popover.scss";
|
||||
|
@ -1,11 +1,35 @@
|
||||
@import "./config.scss";
|
||||
|
||||
@mixin b($block) {
|
||||
$B: $namespace + "-" + $block;
|
||||
$B: null;
|
||||
$BE: null;
|
||||
$BEM: null;
|
||||
|
||||
@mixin b($block) {
|
||||
$temp-block: $B;
|
||||
$temp-block-element: $BE;
|
||||
$B: $namespace + "-" + $block !global;
|
||||
$BE: $B!global;
|
||||
.#{$B} {
|
||||
@content;
|
||||
}
|
||||
$B: $temp-block !global;
|
||||
$BE: $temp-block-element !global;
|
||||
}
|
||||
|
||||
@mixin e($element) {
|
||||
$temp-block-element: $BE;
|
||||
$BE: $B + "__" + $element !global;
|
||||
.#{$BE} {
|
||||
@content
|
||||
}
|
||||
$BE: $temp-block-element !global;
|
||||
}
|
||||
|
||||
@mixin m($modifier) {
|
||||
$BEM: $BE + '--' + $modifier;
|
||||
&.#{$BEM} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
@mixin detachedContentWrapper {
|
||||
|
@ -218,4 +218,50 @@ $scrollbar-color--hover: rgba(255,255,255,0.3);
|
||||
&.#{$namespace}-#{$block}--transition-leave-to {
|
||||
transition: opacity $duration $default-cubic-bezier;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin slide-right-transition($block, $duration: .2s, $delay: .2s) {
|
||||
&.#{$namespace}-#{$block}--transition-leave-active {
|
||||
transition: transform $duration $slow-out-cubic-bezier, max-height $duration $default-cubic-bezier $delay;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter-active {
|
||||
transition: transform $duration $fast-in-cubic-bezier $delay, max-height $duration $default-cubic-bezier;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter-to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter {
|
||||
transform: translateX(150%);
|
||||
max-height: 0;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-leave {
|
||||
transform: translateX(0);
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-leave-to {
|
||||
transform: translateX(150%);
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin slide-left-transition($block, $duration: .2s, $delay: .2s) {
|
||||
&.#{$namespace}-#{$block}--transition-leave-active {
|
||||
transition: transform $duration $slow-out-cubic-bezier, max-height $duration $default-cubic-bezier $delay;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter-active {
|
||||
transition: transform $duration $fast-in-cubic-bezier $delay, max-height $duration $default-cubic-bezier;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter-to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-enter {
|
||||
transform: translateX(-150%);
|
||||
max-height: 0;
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-leave {
|
||||
transform: translateX(0);
|
||||
}
|
||||
&.#{$namespace}-#{$block}--transition-leave-to {
|
||||
transform: translateX(-150%);
|
||||
max-height: 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user