mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-30 12:52:43 +08:00
refactor(select): empty status & data utils
This commit is contained in:
parent
554052e1fe
commit
3b9e318887
@ -6,6 +6,7 @@
|
|||||||
'n-base-select-menu--multiple': multiple,
|
'n-base-select-menu--multiple': multiple,
|
||||||
[`n-${theme}-theme`]: theme
|
[`n-${theme}-theme`]: theme
|
||||||
}"
|
}"
|
||||||
|
|
||||||
:style="{
|
:style="{
|
||||||
width: width && (width + 'px')
|
width: width && (width + 'px')
|
||||||
}"
|
}"
|
||||||
@ -14,6 +15,7 @@
|
|||||||
@mousedown.prevent="() => {}"
|
@mousedown.prevent="() => {}"
|
||||||
>
|
>
|
||||||
<n-scrollbar
|
<n-scrollbar
|
||||||
|
v-show="!empty"
|
||||||
ref="scrollbar"
|
ref="scrollbar"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:without-scrollbar="withoutScrollbar"
|
:without-scrollbar="withoutScrollbar"
|
||||||
@ -22,7 +24,7 @@
|
|||||||
@scroll="handleMenuScroll"
|
@scroll="handleMenuScroll"
|
||||||
>
|
>
|
||||||
<div class="n-base-select-menu-option-wrapper">
|
<div class="n-base-select-menu-option-wrapper">
|
||||||
<template v-if="!loading">
|
<template v-show="empty">
|
||||||
<recycle-scroller
|
<recycle-scroller
|
||||||
ref="virtualScroller"
|
ref="virtualScroller"
|
||||||
class="n-virtual-scroller"
|
class="n-virtual-scroller"
|
||||||
@ -54,39 +56,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
<div
|
<div
|
||||||
v-if="loading"
|
v-if="empty"
|
||||||
class="n-base-select-option n-base-select-option--loading"
|
style="padding: 14px 0;"
|
||||||
>
|
>
|
||||||
loading
|
<slot name="empty">
|
||||||
</div>
|
<n-empty description="No Data" />
|
||||||
<div
|
</slot>
|
||||||
v-else-if="noData"
|
|
||||||
class="n-base-select-option n-base-select-option--no-data"
|
|
||||||
>
|
|
||||||
{{ noDataContent }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="notFound"
|
|
||||||
class="n-base-select-option n-base-select-option--not-found"
|
|
||||||
>
|
|
||||||
{{ notFoundContent }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NScrollbar from '../../../common/Scrollbar'
|
import NScrollbar from '../../../common/Scrollbar'
|
||||||
|
import NSelectOption from './SelectOption.vue'
|
||||||
|
import NSelectGroupHeader from './SelectGroupHeader.vue'
|
||||||
|
import NBaseLightBar from '../../LightBar'
|
||||||
|
import NEmpty from '../../../common/Empty'
|
||||||
|
import { RecycleScroller } from 'vue-virtual-scroller'
|
||||||
|
import debounce from 'lodash-es/debounce'
|
||||||
import {
|
import {
|
||||||
getPrevAvailableIndex,
|
getPrevAvailableIndex,
|
||||||
getNextAvailableIndex,
|
getNextAvailableIndex,
|
||||||
flattenOptions,
|
flattenOptions,
|
||||||
OPTION_TYPE
|
OPTION_TYPE
|
||||||
} from '../../../utils/data/flattenedOptions'
|
} from '../../../utils/component/select'
|
||||||
import NSelectOption from './SelectOption.vue'
|
|
||||||
import NSelectGroupHeader from './SelectGroupHeader.vue'
|
|
||||||
import NBaseLightBar from '../../LightBar'
|
|
||||||
import debounce from 'lodash-es/debounce'
|
|
||||||
import { RecycleScroller } from 'vue-virtual-scroller'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NBaseSelectMenu',
|
name: 'NBaseSelectMenu',
|
||||||
@ -99,6 +92,7 @@ export default {
|
|||||||
NScrollbar,
|
NScrollbar,
|
||||||
NBaseLightBar,
|
NBaseLightBar,
|
||||||
NSelectOption,
|
NSelectOption,
|
||||||
|
NEmpty,
|
||||||
NSelectGroupHeader,
|
NSelectGroupHeader,
|
||||||
RecycleScroller
|
RecycleScroller
|
||||||
},
|
},
|
||||||
@ -131,10 +125,6 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'default'
|
default: 'default'
|
||||||
},
|
},
|
||||||
loading: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
pattern: {
|
pattern: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
@ -155,14 +145,6 @@ export default {
|
|||||||
emitOption: {
|
emitOption: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
|
||||||
noDataContent: {
|
|
||||||
type: [String, Function],
|
|
||||||
default: 'no data'
|
|
||||||
},
|
|
||||||
notFoundContent: {
|
|
||||||
type: [String, Function],
|
|
||||||
default: 'none result matched'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@ -182,11 +164,9 @@ export default {
|
|||||||
const flattenedOptions = flattenOptions(this.options)
|
const flattenedOptions = flattenOptions(this.options)
|
||||||
return flattenedOptions
|
return flattenedOptions
|
||||||
},
|
},
|
||||||
notFound () {
|
empty () {
|
||||||
return this.filterable && (this.pattern.length && !this.flattenedOptions.length)
|
const flattenedOptions = this.flattenedOptions
|
||||||
},
|
return flattenedOptions && flattenedOptions.length === 0
|
||||||
noData () {
|
|
||||||
return this.flattenedOptions && this.flattenedOptions.length === 0
|
|
||||||
},
|
},
|
||||||
itemSize () {
|
itemSize () {
|
||||||
return ({
|
return ({
|
||||||
@ -197,17 +177,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
notFound (value) {
|
empty (value) {
|
||||||
if (value) {
|
|
||||||
this.hideLightBar(0)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
noData (value) {
|
|
||||||
if (value) {
|
|
||||||
this.hideLightBar(0)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
loading (value) {
|
|
||||||
if (value) {
|
if (value) {
|
||||||
this.hideLightBar(0)
|
this.hideLightBar(0)
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
export const createValueAttribute = function createValueAttribute (value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return 's-' + value
|
|
||||||
} else if (typeof value === 'number') {
|
|
||||||
return 'd-' + String(value)
|
|
||||||
} else {
|
|
||||||
console.error(['[naive-ui/select-option]: option value is neither string or number'])
|
|
||||||
return 'invalid'
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,7 @@
|
|||||||
:style="synthesizedStyle"
|
:style="synthesizedStyle"
|
||||||
>
|
>
|
||||||
<div class="n-empty__icon">
|
<div class="n-empty__icon">
|
||||||
<empty-icon />
|
<ios-remove-circle-outline />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showDescription" class="n-empty__description">
|
<div v-if="showDescription" class="n-empty__description">
|
||||||
<slot>
|
<slot>
|
||||||
@ -21,14 +21,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import EmptyIcon from './EmptyIcon'
|
|
||||||
import withapp from '../../../mixins/withapp'
|
import withapp from '../../../mixins/withapp'
|
||||||
import themeable from '../../../mixins/themeable'
|
import themeable from '../../../mixins/themeable'
|
||||||
|
import iosRemoveCircleOutline from '../../../icons/ios-remove-circle-outline'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NEmpty',
|
name: 'NEmpty',
|
||||||
components: {
|
components: {
|
||||||
EmptyIcon
|
iosRemoveCircleOutline
|
||||||
},
|
},
|
||||||
mixins: [ withapp, themeable ],
|
mixins: [ withapp, themeable ],
|
||||||
props: {
|
props: {
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
import Select from './src/Select.vue'
|
import Select from './src/Select.vue'
|
||||||
import SelectOption from './src/SelectOption.vue'
|
|
||||||
|
|
||||||
Select.install = function (Vue) {
|
Select.install = function (Vue) {
|
||||||
Vue.component(Select.name, Select)
|
Vue.component(Select.name, Select)
|
||||||
Vue.component('NSelectOption', SelectOption)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Select
|
export default Select
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:size="size"
|
:size="size"
|
||||||
:theme="synthesizedTheme"
|
:theme="synthesizedTheme"
|
||||||
|
:loading="loading"
|
||||||
@click="handleActivatorClick"
|
@click="handleActivatorClick"
|
||||||
@delete-last-option="handleDeleteLastOption"
|
@delete-last-option="handleDeleteLastOption"
|
||||||
@delete-option="handleToggleOption"
|
@delete-option="handleToggleOption"
|
||||||
@ -64,16 +65,23 @@
|
|||||||
:options="filteredOptions"
|
:options="filteredOptions"
|
||||||
:multiple="multiple"
|
:multiple="multiple"
|
||||||
:size="size"
|
:size="size"
|
||||||
:loading="loading"
|
|
||||||
:no-data-content="noDataContent"
|
|
||||||
:not-found-content="notFoundContent"
|
|
||||||
:filterable="filterable"
|
:filterable="filterable"
|
||||||
:is-option-selected="isOptionSelected"
|
:is-option-selected="isOptionSelected"
|
||||||
:mirror="false"
|
:mirror="false"
|
||||||
@menu-toggle-option="handleToggleOption"
|
@menu-toggle-option="handleToggleOption"
|
||||||
@menu-scroll="handleMenuScroll"
|
@menu-scroll="handleMenuScroll"
|
||||||
@menu-visible="handleMenuVisible"
|
@menu-visible="handleMenuVisible"
|
||||||
/>
|
>
|
||||||
|
<template v-if="$slots.empty" v-slot:empty>
|
||||||
|
<slot name="empty" />
|
||||||
|
</template>
|
||||||
|
<template v-if="$slots.unmatch" v-slot:unmatch>
|
||||||
|
<slot name="unmatch" />
|
||||||
|
</template>
|
||||||
|
<template v-if="$slots.action" v-slot:action>
|
||||||
|
<slot name="action" />
|
||||||
|
</template>
|
||||||
|
</n-base-select-menu>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -91,7 +99,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
filterOptions,
|
filterOptions,
|
||||||
valueToOptionMap
|
valueToOptionMap
|
||||||
} from '../../../utils/data/flattenedOptions'
|
} from '../../../utils/component/select'
|
||||||
import NBasePicker from '../../../base/Picker'
|
import NBasePicker from '../../../base/Picker'
|
||||||
import withapp from '../../../mixins/withapp'
|
import withapp from '../../../mixins/withapp'
|
||||||
import themeable from '../../../mixins/themeable'
|
import themeable from '../../../mixins/themeable'
|
||||||
@ -193,14 +201,6 @@ export default {
|
|||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: undefined
|
default: undefined
|
||||||
},
|
|
||||||
noDataContent: {
|
|
||||||
type: [String, Function],
|
|
||||||
default: 'No Data'
|
|
||||||
},
|
|
||||||
notFoundContent: {
|
|
||||||
type: [String, Function],
|
|
||||||
default: 'No Result'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@ -208,8 +208,7 @@ export default {
|
|||||||
active: false,
|
active: false,
|
||||||
scrolling: false,
|
scrolling: false,
|
||||||
pattern: '',
|
pattern: '',
|
||||||
memorizedValueToOptionMap: new Map(),
|
memorizedValueToOptionMap: new Map()
|
||||||
disablePlaceableTracingWhenActive: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -273,7 +272,6 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
activate () {
|
activate () {
|
||||||
this.active = true
|
this.active = true
|
||||||
this.disablePlaceableTracingWhenActive = true
|
|
||||||
},
|
},
|
||||||
deactivate () {
|
deactivate () {
|
||||||
this.active = false
|
this.active = false
|
||||||
@ -442,7 +440,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleMenuVisible () {
|
handleMenuVisible () {
|
||||||
this.disablePlaceableTracingWhenActive = false
|
|
||||||
this.updatePosition()
|
this.updatePosition()
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<script>
|
|
||||||
import NBaseSelectOption from '../../../base/SelectMenu/src/SelectOption.vue'
|
|
||||||
|
|
||||||
export default NBaseSelectOption
|
|
||||||
</script>
|
|
@ -86,17 +86,6 @@
|
|||||||
}
|
}
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
@include m(no-data) {
|
|
||||||
color: map-get($map: $--base-select-menu-option-color, $key: "disabled");
|
|
||||||
text-align: center;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
@include m(not-found) {
|
|
||||||
color: map-get($map: $--base-select-menu-option-color, $key: "disabled");
|
|
||||||
text-align: center;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
}
|
|
||||||
@include m(loading) {
|
@include m(loading) {
|
||||||
color: map-get($map: $--base-select-menu-option-color, $key: "disabled");
|
color: map-get($map: $--base-select-menu-option-color, $key: "disabled");
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -10,20 +10,22 @@
|
|||||||
@include e(icon) {
|
@include e(icon) {
|
||||||
@include once {
|
@include once {
|
||||||
transition: fill .3s $--n-ease-in-out-cubic-bezier;
|
transition: fill .3s $--n-ease-in-out-cubic-bezier;
|
||||||
width: 40px;
|
width: 28px;
|
||||||
height: 40px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
fill: $--empty-icon-fill;
|
fill: $--empty-icon-fill;
|
||||||
}
|
}
|
||||||
@include e(description) {
|
@include e(description) {
|
||||||
@include once {
|
@include once {
|
||||||
margin-top: 8px;
|
font-size: 14px;
|
||||||
|
margin-top: 4px;
|
||||||
transition: color .3s $--n-ease-in-out-cubic-bezier;
|
transition: color .3s $--n-ease-in-out-cubic-bezier;
|
||||||
}
|
}
|
||||||
color: $--empty-text-color;
|
color: $--empty-text-color;
|
||||||
}
|
}
|
||||||
@include e(extra) {
|
@include e(extra) {
|
||||||
@include once {
|
@include once {
|
||||||
|
font-size: 14px;;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: color .3s $--n-ease-in-out-cubic-bezier;
|
transition: color .3s $--n-ease-in-out-cubic-bezier;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
Loading…
Reference in New Issue
Block a user