diff options
Diffstat (limited to 'src/components/selectable_list')
| -rw-r--r-- | src/components/selectable_list/selectable_list.js | 66 | ||||
| -rw-r--r-- | src/components/selectable_list/selectable_list.vue | 63 |
2 files changed, 129 insertions, 0 deletions
diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js new file mode 100644 index 00000000..10980d46 --- /dev/null +++ b/src/components/selectable_list/selectable_list.js @@ -0,0 +1,66 @@ +import List from '../list/list.vue' +import Checkbox from '../checkbox/checkbox.vue' + +const SelectableList = { + components: { + List, + Checkbox + }, + props: { + items: { + type: Array, + default: () => [] + }, + getKey: { + type: Function, + default: item => item.id + } + }, + data () { + return { + selected: [] + } + }, + computed: { + allKeys () { + return this.items.map(this.getKey) + }, + filteredSelected () { + return this.allKeys.filter(key => this.selected.indexOf(key) !== -1) + }, + allSelected () { + return this.filteredSelected.length === this.items.length + }, + noneSelected () { + return this.filteredSelected.length === 0 + }, + someSelected () { + return !this.allSelected && !this.noneSelected + } + }, + methods: { + isSelected (item) { + return this.filteredSelected.indexOf(this.getKey(item)) !== -1 + }, + toggle (checked, item) { + const key = this.getKey(item) + const oldChecked = this.isSelected(key) + if (checked !== oldChecked) { + if (checked) { + this.selected.push(key) + } else { + this.selected.splice(this.selected.indexOf(key), 1) + } + } + }, + toggleAll (value) { + if (value) { + this.selected = this.allKeys.slice(0) + } else { + this.selected = [] + } + } + } +} + +export default SelectableList diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue new file mode 100644 index 00000000..3f16c921 --- /dev/null +++ b/src/components/selectable_list/selectable_list.vue @@ -0,0 +1,63 @@ +<template> + <div class="selectable-list"> + <div class="selectable-list-header" v-if="items.length > 0"> + <div class="selectable-list-checkbox-wrapper"> + <Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox> + </div> + <div class="selectable-list-header-actions"> + <slot name="header" :selected="filteredSelected" /> + </div> + </div> + <List :items="items" :getKey="getKey"> + <template slot="item" slot-scope="{item}"> + <div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }"> + <div class="selectable-list-checkbox-wrapper"> + <Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" /> + </div> + <slot name="item" :item="item" /> + </div> + </template> + <template slot="empty"><slot name="empty" /></template> + </List> + </div> +</template> + +<script src="./selectable_list.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.selectable-list { + &-item-inner { + display: flex; + align-items: center; + + > * { + min-width: 0; + } + } + + &-item-selected-inner { + background-color: $fallback--lightBg; + background-color: var(--lightBg, $fallback--lightBg); + } + + &-header { + display: flex; + align-items: center; + padding: 0.6em 0; + border-bottom: 2px solid; + border-bottom-color: $fallback--border; + border-bottom-color: var(--border, $fallback--border); + + &-actions { + flex: 1; + } + } + + &-checkbox-wrapper { + padding: 0 10px; + flex: none; + } +} +</style> |
