mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-12 12:25:16 +08:00
refactor(base-select-menu): ts
This commit is contained in:
parent
9e095c1a6a
commit
5faf1a8870
@ -1,2 +0,0 @@
|
|||||||
/* istanbul ignore file */
|
|
||||||
export { default } from './src/SelectMenu.vue'
|
|
2
src/_base/select-menu/index.ts
Normal file
2
src/_base/select-menu/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/* istanbul ignore file */
|
||||||
|
export { default } from './src/SelectMenu'
|
@ -1,10 +1,11 @@
|
|||||||
import { h, defineComponent } from 'vue'
|
import { h, defineComponent, PropType } from 'vue'
|
||||||
|
import { TreeNode } from 'treemate'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'NBaseSelectGroupHeader',
|
name: 'NBaseSelectGroupHeader',
|
||||||
props: {
|
props: {
|
||||||
tmNode: {
|
tmNode: {
|
||||||
type: Object,
|
type: Object as PropType<TreeNode>,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
387
src/_base/select-menu/src/SelectMenu.tsx
Normal file
387
src/_base/select-menu/src/SelectMenu.tsx
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
import {
|
||||||
|
h,
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
PropType,
|
||||||
|
watch,
|
||||||
|
toRef,
|
||||||
|
renderSlot,
|
||||||
|
VNode,
|
||||||
|
provide,
|
||||||
|
reactive
|
||||||
|
} from 'vue'
|
||||||
|
import { RawNode, TreeMate, TreeNode } from 'treemate'
|
||||||
|
import { VirtualList, VirtualListRef } from 'vueuc'
|
||||||
|
import { depx, getPadding } from 'seemly'
|
||||||
|
import { NEmpty } from '../../../empty'
|
||||||
|
import { NScrollbar } from '../../../scrollbar'
|
||||||
|
import type { ScrollbarRef } from '../../../scrollbar'
|
||||||
|
import { formatLength } from '../../../_utils'
|
||||||
|
import { createKey } from '../../../_utils/cssr'
|
||||||
|
import { useTheme } from '../../../_mixins'
|
||||||
|
import type { ThemeProps } from '../../../_mixins'
|
||||||
|
import NSelectOption from './SelectOption'
|
||||||
|
import NSelectGroupHeader from './SelectGroupHeader'
|
||||||
|
import style from './styles/index.cssr'
|
||||||
|
import { baseSelectMenuLight, BaseSelectMenuTheme } from '../styles'
|
||||||
|
|
||||||
|
export interface BaseSelectMenuInjection {
|
||||||
|
handleOptionMouseEnter: (e: MouseEvent, tmNode: TreeNode) => void
|
||||||
|
handleOptionClick: (e: MouseEvent, tmNode: TreeNode) => void
|
||||||
|
valueSet: Set<number | string>
|
||||||
|
pendingTmNode: TreeNode | null
|
||||||
|
multiple: boolean
|
||||||
|
value: string | number | Array<string | number> | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BaseSelectMenuRef {
|
||||||
|
getPendingOption: () => TreeNode | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'BaseSelectMenu',
|
||||||
|
props: {
|
||||||
|
...(useTheme.props as ThemeProps<BaseSelectMenuTheme>),
|
||||||
|
scrollable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
treeMate: {
|
||||||
|
type: Object as PropType<TreeMate>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String as PropType<'small' | 'medium' | 'large'>,
|
||||||
|
default: 'medium'
|
||||||
|
},
|
||||||
|
pattern: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Array] as PropType<
|
||||||
|
string | number | null | Array<string | number>
|
||||||
|
>,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
autoPending: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
virtualScroll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
onScroll: {
|
||||||
|
type: Function as PropType<((e: Event) => void) | undefined>,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
// deprecated
|
||||||
|
onMenuToggleOption: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup (props) {
|
||||||
|
const themeRef = useTheme(
|
||||||
|
'BaseSelectMenu',
|
||||||
|
'BaseSelectMenu',
|
||||||
|
style,
|
||||||
|
baseSelectMenuLight,
|
||||||
|
props
|
||||||
|
)
|
||||||
|
const virtualListRef = ref<VirtualListRef | null>(null)
|
||||||
|
const scrollbarRef = ref<ScrollbarRef | null>(null)
|
||||||
|
const { treeMate } = props
|
||||||
|
const pendingNodeRef = ref(
|
||||||
|
props.autoPending
|
||||||
|
? props.value === null
|
||||||
|
? treeMate.getFirstAvailableNode()
|
||||||
|
: props.multiple
|
||||||
|
? treeMate.getNode(
|
||||||
|
((props.value as Array<string | number> | null) || [])[
|
||||||
|
((props.value as Array<string | number> | null) || []).length -
|
||||||
|
1
|
||||||
|
]
|
||||||
|
) || treeMate.getFirstAvailableNode()
|
||||||
|
: treeMate.getNode(props.value as string | number) ||
|
||||||
|
treeMate.getFirstAvailableNode()
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
const itemSizeRef = computed(() => {
|
||||||
|
return depx(themeRef.value.self[createKey('optionHeight', props.size)])
|
||||||
|
})
|
||||||
|
const paddingRef = computed(() => {
|
||||||
|
return getPadding(themeRef.value.self[createKey('padding', props.size)])
|
||||||
|
})
|
||||||
|
const valueSetRef = computed(() => {
|
||||||
|
if (props.multiple && Array.isArray(props.value)) {
|
||||||
|
return new Set(props.value)
|
||||||
|
}
|
||||||
|
return new Set<string | number>()
|
||||||
|
})
|
||||||
|
const emptyRef = computed(() => {
|
||||||
|
const tmNodes = props.treeMate.flattenedNodes
|
||||||
|
return tmNodes && tmNodes.length === 0
|
||||||
|
})
|
||||||
|
const styleRef = computed(() => {
|
||||||
|
return [{ width: formatLength(props.width) }, cssVarsRef.value]
|
||||||
|
})
|
||||||
|
const tmNodesRef = computed(() => {
|
||||||
|
return props.treeMate.treeNodes
|
||||||
|
})
|
||||||
|
watch(toRef(props, 'treeMate'), () => {
|
||||||
|
if (props.autoPending) {
|
||||||
|
const tmNode = props.treeMate.getFirstAvailableNode()
|
||||||
|
setPendingTmNode(tmNode)
|
||||||
|
} else {
|
||||||
|
setPendingTmNode(null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
function doToggleOption (option: RawNode): void {
|
||||||
|
const { onMenuToggleOption } = props
|
||||||
|
if (onMenuToggleOption) onMenuToggleOption(option)
|
||||||
|
}
|
||||||
|
function doScroll (e: Event): void {
|
||||||
|
const { onScroll } = props
|
||||||
|
if (onScroll) onScroll(e)
|
||||||
|
}
|
||||||
|
// required, scroller sync need to be triggered manually
|
||||||
|
function handleVirtualListScroll (e: Event): void {
|
||||||
|
scrollbarRef.value?.sync()
|
||||||
|
doScroll(e)
|
||||||
|
}
|
||||||
|
function handleVirtualListResize (): void {
|
||||||
|
scrollbarRef.value?.sync()
|
||||||
|
}
|
||||||
|
function getPendingOption (): RawNode | null {
|
||||||
|
const { value: pendingTmNode } = pendingNodeRef
|
||||||
|
if (pendingTmNode) return pendingTmNode.rawNode
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
function handleOptionMouseEnter (e: MouseEvent, tmNode: TreeNode): void {
|
||||||
|
if (tmNode.disabled) return
|
||||||
|
setPendingTmNode(tmNode, false)
|
||||||
|
}
|
||||||
|
function handleOptionClick (e: MouseEvent, tmNode: TreeNode): void {
|
||||||
|
if (tmNode.disabled) return
|
||||||
|
doToggleOption(tmNode.rawNode)
|
||||||
|
}
|
||||||
|
// keyboard related methods
|
||||||
|
function handleKeyUp (e: KeyboardEvent): void {
|
||||||
|
switch (e.code) {
|
||||||
|
case 'ArrowUp':
|
||||||
|
prev()
|
||||||
|
break
|
||||||
|
case 'ArrowDown':
|
||||||
|
next()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleMouseDown (e: MouseEvent): void {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
function next (): void {
|
||||||
|
const { value: pendingTmNode } = pendingNodeRef
|
||||||
|
if (pendingTmNode) {
|
||||||
|
setPendingTmNode(pendingTmNode.getNext({ loop: true }), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function prev (): void {
|
||||||
|
const { value: pendingTmNode } = pendingNodeRef
|
||||||
|
if (pendingTmNode) {
|
||||||
|
setPendingTmNode(pendingTmNode.getPrev({ loop: true }), true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setPendingTmNode (tmNode: TreeNode | null, doScroll = false): void {
|
||||||
|
pendingNodeRef.value = tmNode
|
||||||
|
if (doScroll && tmNode) {
|
||||||
|
if (props.virtualScroll) {
|
||||||
|
virtualListRef.value?.scrollTo({ index: tmNode.fIndex })
|
||||||
|
} else {
|
||||||
|
scrollbarRef.value?.scrollTo({
|
||||||
|
index: tmNode.fIndex,
|
||||||
|
elSize: itemSizeRef.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
provide<BaseSelectMenuInjection>(
|
||||||
|
'NBaseSelectMenu',
|
||||||
|
reactive({
|
||||||
|
handleOptionMouseEnter,
|
||||||
|
handleOptionClick,
|
||||||
|
valueSet: valueSetRef,
|
||||||
|
multiple: toRef(props, 'multiple'),
|
||||||
|
value: toRef(props, 'value'),
|
||||||
|
pendingTmNode: pendingNodeRef
|
||||||
|
})
|
||||||
|
)
|
||||||
|
onMounted(() => {
|
||||||
|
const { value } = scrollbarRef
|
||||||
|
if (value) value.sync()
|
||||||
|
})
|
||||||
|
const cssVarsRef = computed(() => {
|
||||||
|
const { size } = props
|
||||||
|
const {
|
||||||
|
common: { cubicBezierEaseInOut },
|
||||||
|
self: {
|
||||||
|
borderRadius,
|
||||||
|
color,
|
||||||
|
boxShadow,
|
||||||
|
groupHeaderTextColor,
|
||||||
|
actionDividerColor,
|
||||||
|
optionTextColorPressed,
|
||||||
|
optionTextColor,
|
||||||
|
optionTextColorDisabled,
|
||||||
|
optionTextColorActive,
|
||||||
|
optionOpacityDisabled,
|
||||||
|
optionCheckColor,
|
||||||
|
actionTextColor,
|
||||||
|
optionColorPending,
|
||||||
|
[createKey('optionFontSize', size)]: fontSize,
|
||||||
|
[createKey('optionHeight', size)]: optionHeight
|
||||||
|
}
|
||||||
|
} = themeRef.value
|
||||||
|
return {
|
||||||
|
'--action-divider-color': actionDividerColor,
|
||||||
|
'--action-text-color': actionTextColor,
|
||||||
|
'--bezier': cubicBezierEaseInOut,
|
||||||
|
'--border-radius': borderRadius,
|
||||||
|
'--box-shadow': boxShadow,
|
||||||
|
'--color': color,
|
||||||
|
'--option-font-size': fontSize,
|
||||||
|
'--group-header-text-color': groupHeaderTextColor,
|
||||||
|
'--option-check-color': optionCheckColor,
|
||||||
|
'--option-color-pending': optionColorPending,
|
||||||
|
'--option-height': optionHeight,
|
||||||
|
'--option-opacity-disabled': optionOpacityDisabled,
|
||||||
|
'--option-text-color': optionTextColor,
|
||||||
|
'--option-text-color-active': optionTextColorActive,
|
||||||
|
'--option-text-color-disabled': optionTextColorDisabled,
|
||||||
|
'--option-text-color-pressed': optionTextColorPressed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
virtualListRef,
|
||||||
|
scrollbarRef,
|
||||||
|
style: styleRef,
|
||||||
|
defaultScrollIndex: pendingNodeRef.value?.fIndex,
|
||||||
|
itemSize: itemSizeRef,
|
||||||
|
padding: paddingRef,
|
||||||
|
tmNodes: tmNodesRef,
|
||||||
|
empty: emptyRef,
|
||||||
|
next,
|
||||||
|
prev,
|
||||||
|
virtualListContainer () {
|
||||||
|
const { value } = virtualListRef
|
||||||
|
return value?.listRef as HTMLElement
|
||||||
|
},
|
||||||
|
virtualListContent () {
|
||||||
|
const { value } = virtualListRef
|
||||||
|
return value?.itemsRef as HTMLElement
|
||||||
|
},
|
||||||
|
doScroll,
|
||||||
|
handleKeyUp,
|
||||||
|
handleMouseDown,
|
||||||
|
handleVirtualListResize,
|
||||||
|
handleVirtualListScroll,
|
||||||
|
getPendingOption
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
const { $slots, virtualScroll } = this
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
class={[
|
||||||
|
'n-base-select-menu',
|
||||||
|
{
|
||||||
|
'n-base-select-menu--multiple': this.multiple
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
style={this.style as any}
|
||||||
|
onKeyup={this.handleKeyUp}
|
||||||
|
onMousedown={this.handleMouseDown}
|
||||||
|
>
|
||||||
|
{!this.empty ? (
|
||||||
|
<NScrollbar
|
||||||
|
ref="scrollbarRef"
|
||||||
|
scrollable={this.scrollable}
|
||||||
|
container={virtualScroll ? this.virtualListContainer : undefined}
|
||||||
|
content={virtualScroll ? this.virtualListContent : undefined}
|
||||||
|
onScroll={this.doScroll}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => {
|
||||||
|
return virtualScroll ? (
|
||||||
|
<VirtualList
|
||||||
|
ref="virtualListRef"
|
||||||
|
class="n-virtual-list"
|
||||||
|
items={this.tmNodes}
|
||||||
|
itemSize={this.itemSize}
|
||||||
|
showScrollbar={false}
|
||||||
|
defaultScrollIndex={this.defaultScrollIndex}
|
||||||
|
paddingTop={this.padding.top}
|
||||||
|
paddingBottom={this.padding.bottom}
|
||||||
|
onResize={this.handleVirtualListResize}
|
||||||
|
onScroll={this.handleVirtualListScroll}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: ({ item: tmNode }: { item: TreeNode }) => {
|
||||||
|
return tmNode.rawNode.type === 'group' ? (
|
||||||
|
<NSelectGroupHeader
|
||||||
|
key={tmNode.key}
|
||||||
|
tmNode={tmNode}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<NSelectOption key={tmNode.key} tmNode={tmNode} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</VirtualList>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
class="n-base-select-menu-option-wrapper"
|
||||||
|
style={{
|
||||||
|
paddingTop: this.padding.top,
|
||||||
|
paddingBottom: this.padding.bottom
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.tmNodes.map((tmNode) =>
|
||||||
|
tmNode.rawNode.type === 'group' ? (
|
||||||
|
<NSelectGroupHeader key={tmNode.key} tmNode={tmNode} />
|
||||||
|
) : (
|
||||||
|
<NSelectOption key={tmNode.key} tmNode={tmNode} />
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</NScrollbar>
|
||||||
|
) : (
|
||||||
|
<div style="padding: 14px 0; width: 100%">
|
||||||
|
{renderSlot($slots, 'empty', undefined, () => [
|
||||||
|
(<NEmpty />) as VNode
|
||||||
|
])}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{$slots.action && (
|
||||||
|
<div class="n-base-select-menu__action">
|
||||||
|
{renderSlot($slots, 'action')}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
@ -1,327 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="n-base-select-menu"
|
|
||||||
:class="{
|
|
||||||
'n-base-select-menu--multiple': multiple
|
|
||||||
}"
|
|
||||||
:style="style"
|
|
||||||
@keyup.up.stop="handleKeyUpUp"
|
|
||||||
@keyup.down.stop="handleKeyUpDown"
|
|
||||||
@mousedown.prevent
|
|
||||||
>
|
|
||||||
<n-scrollbar
|
|
||||||
v-if="!empty"
|
|
||||||
ref="scrollbarRef"
|
|
||||||
:scrollable="scrollable"
|
|
||||||
:container="virtualScroll ? virtualListContainer : undefined"
|
|
||||||
:content="virtualScroll ? virtualListContent : undefined"
|
|
||||||
@scroll="doScroll"
|
|
||||||
>
|
|
||||||
<virtual-list
|
|
||||||
v-if="virtualScroll"
|
|
||||||
ref="virtualListRef"
|
|
||||||
class="n-virtual-list"
|
|
||||||
:items="tmNodes"
|
|
||||||
:item-size="itemSize"
|
|
||||||
:show-scrollbar="false"
|
|
||||||
:default-scroll-index="defaultScrollIndex"
|
|
||||||
:padding-top="padding.top"
|
|
||||||
:padding-bottom="padding.bottom"
|
|
||||||
@resize="handleVirtualListResize"
|
|
||||||
@scroll="handleVirtualListScroll"
|
|
||||||
>
|
|
||||||
<template #default="{ item: tmNode }">
|
|
||||||
<n-select-group-header
|
|
||||||
v-if="tmNode.rawNode.type === 'group'"
|
|
||||||
:key="tmNode.key"
|
|
||||||
:tm-node="tmNode"
|
|
||||||
/>
|
|
||||||
<n-select-option v-else :key="tmNode.key" :tm-node="tmNode" />
|
|
||||||
</template>
|
|
||||||
</virtual-list>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="n-base-select-menu-option-wrapper"
|
|
||||||
:style="{
|
|
||||||
paddingTop: padding.top,
|
|
||||||
paddingBottom: padding.bottom
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template v-for="tmNode in tmNodes">
|
|
||||||
<n-select-group-header
|
|
||||||
v-if="tmNode.rawNode.type === 'group'"
|
|
||||||
:key="tmNode.key"
|
|
||||||
:tm-node="tmNode"
|
|
||||||
/>
|
|
||||||
<n-select-option v-else :key="tmNode.key" :tm-node="tmNode" />
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</n-scrollbar>
|
|
||||||
<div v-else style="padding: 14px 0; width: 100%">
|
|
||||||
<slot name="empty">
|
|
||||||
<n-empty />
|
|
||||||
</slot>
|
|
||||||
</div>
|
|
||||||
<div v-if="$slots.action" class="n-base-select-menu__action">
|
|
||||||
<slot name="action" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ref, onMounted, computed, defineComponent } from 'vue'
|
|
||||||
import { VirtualList } from 'vueuc'
|
|
||||||
import { depx, getPadding } from 'seemly'
|
|
||||||
import { NEmpty } from '../../../empty'
|
|
||||||
import { NScrollbar } from '../../../scrollbar'
|
|
||||||
import { formatLength } from '../../../_utils'
|
|
||||||
import { createKey } from '../../../_utils/cssr'
|
|
||||||
import { useTheme } from '../../../_mixins'
|
|
||||||
import NSelectOption from './SelectOption.js'
|
|
||||||
import NSelectGroupHeader from './SelectGroupHeader.js'
|
|
||||||
import style from './styles/index.cssr.js'
|
|
||||||
import { baseSelectMenuLight } from '../styles'
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'BaseSelectMenu',
|
|
||||||
components: {
|
|
||||||
VirtualList,
|
|
||||||
NScrollbar,
|
|
||||||
NSelectOption,
|
|
||||||
NEmpty,
|
|
||||||
NSelectGroupHeader
|
|
||||||
},
|
|
||||||
provide () {
|
|
||||||
return {
|
|
||||||
NBaseSelectMenu: this
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
...useTheme.props,
|
|
||||||
scrollable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
treeMate: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
multiple: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
type: String,
|
|
||||||
default: 'medium'
|
|
||||||
},
|
|
||||||
pattern: {
|
|
||||||
type: String,
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
type: [String, Number, Array],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
autoPending: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
virtualScroll: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
onScroll: {
|
|
||||||
type: Function,
|
|
||||||
default: undefined
|
|
||||||
},
|
|
||||||
// deprecated
|
|
||||||
onMenuToggleOption: {
|
|
||||||
type: Function,
|
|
||||||
default: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup (props) {
|
|
||||||
const themeRef = useTheme(
|
|
||||||
'BaseSelectMenu',
|
|
||||||
'BaseSelectMenu',
|
|
||||||
style,
|
|
||||||
baseSelectMenuLight,
|
|
||||||
props
|
|
||||||
)
|
|
||||||
const virtualListRef = ref(null)
|
|
||||||
const scrollbarRef = ref(null)
|
|
||||||
const { treeMate } = props
|
|
||||||
const pendingNodeRef = ref(
|
|
||||||
props.autoPending
|
|
||||||
? props.value === null
|
|
||||||
? treeMate.getFirstAvailableNode()
|
|
||||||
: props.multiple
|
|
||||||
? treeMate.getNode(
|
|
||||||
(props.value || [])[(props.value || []).length - 1]
|
|
||||||
) || treeMate.getFirstAvailableNode()
|
|
||||||
: treeMate.getNode(props.value) || treeMate.getFirstAvailableNode()
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
const itemSizeRef = computed(() => {
|
|
||||||
return depx(themeRef.value.self[createKey('optionHeight', props.size)])
|
|
||||||
})
|
|
||||||
const paddingRef = computed(() => {
|
|
||||||
return getPadding(themeRef.value.self[createKey('padding', props.size)])
|
|
||||||
})
|
|
||||||
onMounted(() => {
|
|
||||||
const { value } = scrollbarRef
|
|
||||||
if (value) value.sync()
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
tmNodes: computed(() => props.treeMate.flattenedNodes),
|
|
||||||
virtualListRef,
|
|
||||||
scrollbarRef,
|
|
||||||
virtualListContainer () {
|
|
||||||
const { value } = virtualListRef
|
|
||||||
return value && value.listRef
|
|
||||||
},
|
|
||||||
virtualListContent () {
|
|
||||||
const { value } = virtualListRef
|
|
||||||
return value && value.itemsRef
|
|
||||||
},
|
|
||||||
pendingTmNode: pendingNodeRef,
|
|
||||||
defaultScrollIndex: pendingNodeRef.value?.fIndex,
|
|
||||||
itemSize: itemSizeRef,
|
|
||||||
padding: paddingRef,
|
|
||||||
cssVars: computed(() => {
|
|
||||||
const { size } = props
|
|
||||||
const {
|
|
||||||
common: { cubicBezierEaseInOut },
|
|
||||||
self: {
|
|
||||||
borderRadius,
|
|
||||||
color,
|
|
||||||
boxShadow,
|
|
||||||
groupHeaderTextColor,
|
|
||||||
actionDividerColor,
|
|
||||||
optionTextColorPressed,
|
|
||||||
optionTextColor,
|
|
||||||
optionTextColorDisabled,
|
|
||||||
optionTextColorActive,
|
|
||||||
optionOpacityDisabled,
|
|
||||||
optionCheckColor,
|
|
||||||
actionTextColor,
|
|
||||||
optionColorPending,
|
|
||||||
[createKey('optionFontSize', size)]: fontSize,
|
|
||||||
[createKey('optionHeight', size)]: optionHeight
|
|
||||||
}
|
|
||||||
} = themeRef.value
|
|
||||||
return {
|
|
||||||
'--action-divider-color': actionDividerColor,
|
|
||||||
'--action-text-color': actionTextColor,
|
|
||||||
'--bezier': cubicBezierEaseInOut,
|
|
||||||
'--border-radius': borderRadius,
|
|
||||||
'--box-shadow': boxShadow,
|
|
||||||
'--color': color,
|
|
||||||
'--option-font-size': fontSize,
|
|
||||||
'--group-header-text-color': groupHeaderTextColor,
|
|
||||||
'--option-check-color': optionCheckColor,
|
|
||||||
'--option-color-pending': optionColorPending,
|
|
||||||
'--option-height': optionHeight,
|
|
||||||
'--option-opacity-disabled': optionOpacityDisabled,
|
|
||||||
'--option-text-color': optionTextColor,
|
|
||||||
'--option-text-color-active': optionTextColorActive,
|
|
||||||
'--option-text-color-disabled': optionTextColorDisabled,
|
|
||||||
'--option-text-color-pressed': optionTextColorPressed
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
valueSet () {
|
|
||||||
if (this.multiple && Array.isArray(this.value)) return new Set(this.value)
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
empty () {
|
|
||||||
const { tmNodes } = this
|
|
||||||
return tmNodes && tmNodes.length === 0
|
|
||||||
},
|
|
||||||
style () {
|
|
||||||
return {
|
|
||||||
width: formatLength(this.width),
|
|
||||||
...this.cssVars
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
treeMate (value) {
|
|
||||||
if (this.autoPending) {
|
|
||||||
const tmNode = this.treeMate.getFirstAvailableNode()
|
|
||||||
this.setPendingTmNode(tmNode)
|
|
||||||
} else {
|
|
||||||
this.setPendingTmNode(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
doToggleOption (option) {
|
|
||||||
const { onMenuToggleOption } = this
|
|
||||||
if (onMenuToggleOption) onMenuToggleOption(option)
|
|
||||||
},
|
|
||||||
doScroll (e) {
|
|
||||||
const { onScroll } = this
|
|
||||||
if (onScroll) onScroll(e)
|
|
||||||
},
|
|
||||||
// required, scroller sync need to be triggered manually
|
|
||||||
handleVirtualListScroll (e) {
|
|
||||||
this.scrollbarRef.sync()
|
|
||||||
this.doScroll(e)
|
|
||||||
},
|
|
||||||
handleVirtualListResize () {
|
|
||||||
this.scrollbarRef.sync()
|
|
||||||
},
|
|
||||||
getPendingOption () {
|
|
||||||
const { pendingTmNode } = this
|
|
||||||
return pendingTmNode && pendingTmNode.rawNode
|
|
||||||
},
|
|
||||||
handleOptionMouseEnter (e, tmNode) {
|
|
||||||
if (tmNode.disabled) return
|
|
||||||
this.setPendingTmNode(tmNode, false)
|
|
||||||
},
|
|
||||||
handleOptionClick (e, tmNode) {
|
|
||||||
if (tmNode.disabled) return
|
|
||||||
this.doToggleOption(tmNode.rawNode)
|
|
||||||
},
|
|
||||||
// keyboard related methods
|
|
||||||
handleKeyUpUp () {
|
|
||||||
this.prev()
|
|
||||||
},
|
|
||||||
handleKeyUpDown () {
|
|
||||||
this.next()
|
|
||||||
},
|
|
||||||
next () {
|
|
||||||
const { pendingTmNode } = this
|
|
||||||
if (pendingTmNode) {
|
|
||||||
this.setPendingTmNode(pendingTmNode.getNext({ loop: true }), true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prev () {
|
|
||||||
const { pendingTmNode } = this
|
|
||||||
if (pendingTmNode) {
|
|
||||||
this.setPendingTmNode(pendingTmNode.getPrev({ loop: true }), true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setPendingTmNode (tmNode, doScroll = false) {
|
|
||||||
this.pendingTmNode = tmNode
|
|
||||||
if (doScroll) {
|
|
||||||
if (this.virtualScroll) {
|
|
||||||
this.virtualListRef.scrollTo({ index: tmNode.fIndex })
|
|
||||||
} else {
|
|
||||||
this.scrollbarRef.scrollTo({
|
|
||||||
index: tmNode.fIndex,
|
|
||||||
elSize: this.itemSize
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -1,4 +1,14 @@
|
|||||||
import { h, inject, toRef, defineComponent, Transition } from 'vue'
|
import {
|
||||||
|
h,
|
||||||
|
inject,
|
||||||
|
toRef,
|
||||||
|
defineComponent,
|
||||||
|
Transition,
|
||||||
|
PropType,
|
||||||
|
VNode
|
||||||
|
} from 'vue'
|
||||||
|
import { BaseSelectMenuInjection } from './SelectMenu'
|
||||||
|
import { TreeNode } from 'treemate'
|
||||||
import { useMemo } from 'vooks'
|
import { useMemo } from 'vooks'
|
||||||
import { CheckmarkIcon } from '../../icons'
|
import { CheckmarkIcon } from '../../icons'
|
||||||
import NBaseIcon from '../../icon'
|
import NBaseIcon from '../../icon'
|
||||||
@ -7,7 +17,7 @@ const checkMark = h(NBaseIcon, null, {
|
|||||||
default: () => h(CheckmarkIcon)
|
default: () => h(CheckmarkIcon)
|
||||||
})
|
})
|
||||||
|
|
||||||
function renderCheckMark (show) {
|
function renderCheckMark (show: boolean): VNode {
|
||||||
return h(
|
return h(
|
||||||
Transition,
|
Transition,
|
||||||
{
|
{
|
||||||
@ -22,20 +32,38 @@ function renderCheckMark (show) {
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'NBaseSelectOption',
|
name: 'NBaseSelectOption',
|
||||||
inject: {
|
|
||||||
NBaseSelectMenu: {
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
tmNode: {
|
tmNode: {
|
||||||
type: Object,
|
type: Object as PropType<TreeNode>,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
const NBaseSelectMenu = inject('NBaseSelectMenu')
|
const NBaseSelectMenu = inject<BaseSelectMenuInjection>(
|
||||||
|
'NBaseSelectMenu'
|
||||||
|
) as BaseSelectMenuInjection
|
||||||
const rawNodeRef = toRef(props.tmNode, 'rawNode')
|
const rawNodeRef = toRef(props.tmNode, 'rawNode')
|
||||||
|
const isPendingRef = useMemo(() => {
|
||||||
|
const { pendingTmNode } = NBaseSelectMenu
|
||||||
|
if (!pendingTmNode) return false
|
||||||
|
return props.tmNode.key === pendingTmNode.key
|
||||||
|
})
|
||||||
|
function handleClick (e: MouseEvent): void {
|
||||||
|
const { tmNode } = props
|
||||||
|
if (tmNode.disabled) return
|
||||||
|
NBaseSelectMenu.handleOptionClick(e, tmNode)
|
||||||
|
}
|
||||||
|
function handleMouseEnter (e: MouseEvent): void {
|
||||||
|
const { tmNode } = props
|
||||||
|
if (tmNode.disabled) return
|
||||||
|
NBaseSelectMenu.handleOptionMouseEnter(e, tmNode)
|
||||||
|
}
|
||||||
|
function handleMouseMove (e: MouseEvent): void {
|
||||||
|
const { tmNode } = props
|
||||||
|
const { value: isPending } = isPendingRef
|
||||||
|
if (tmNode.disabled || isPending) return
|
||||||
|
NBaseSelectMenu.handleOptionMouseEnter(e, tmNode)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
NBaseSelectMenu,
|
NBaseSelectMenu,
|
||||||
rawNode: rawNodeRef,
|
rawNode: rawNodeRef,
|
||||||
@ -44,11 +72,7 @@ export default defineComponent({
|
|||||||
const { parent } = tmNode
|
const { parent } = tmNode
|
||||||
return parent && parent.rawNode.type === 'group'
|
return parent && parent.rawNode.type === 'group'
|
||||||
}),
|
}),
|
||||||
isPending: useMemo(() => {
|
isPending: isPendingRef,
|
||||||
const { pendingTmNode } = NBaseSelectMenu
|
|
||||||
if (!pendingTmNode) return false
|
|
||||||
return props.tmNode.key === pendingTmNode.key
|
|
||||||
}),
|
|
||||||
isSelected: useMemo(() => {
|
isSelected: useMemo(() => {
|
||||||
const { multiple, value } = NBaseSelectMenu
|
const { multiple, value } = NBaseSelectMenu
|
||||||
if (value === null) return false
|
if (value === null) return false
|
||||||
@ -59,24 +83,10 @@ export default defineComponent({
|
|||||||
} else {
|
} else {
|
||||||
return value === optionValue
|
return value === optionValue
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
}
|
handleMouseMove,
|
||||||
},
|
handleMouseEnter,
|
||||||
methods: {
|
handleClick
|
||||||
handleClick (e) {
|
|
||||||
const { tmNode } = this
|
|
||||||
if (tmNode.disabled) return
|
|
||||||
this.NBaseSelectMenu.handleOptionClick(e, tmNode)
|
|
||||||
},
|
|
||||||
handleMouseEnter (e) {
|
|
||||||
const { tmNode } = this
|
|
||||||
if (tmNode.disabled) return
|
|
||||||
this.NBaseSelectMenu.handleOptionMouseEnter(e, tmNode)
|
|
||||||
},
|
|
||||||
handleMouseMove (e) {
|
|
||||||
const { tmNode, isPending } = this
|
|
||||||
if (tmNode.disabled || isPending) return
|
|
||||||
this.NBaseSelectMenu.handleOptionMouseEnter(e, tmNode)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
@ -90,7 +100,7 @@ export default defineComponent({
|
|||||||
handleMouseMove,
|
handleMouseMove,
|
||||||
NBaseSelectMenu: { multiple }
|
NBaseSelectMenu: { multiple }
|
||||||
} = this
|
} = this
|
||||||
const showCheckMark = multiple & isSelected
|
const showCheckMark = multiple && isSelected
|
||||||
const children = rawNode.render
|
const children = rawNode.render
|
||||||
? [rawNode.render(rawNode, isSelected), renderCheckMark(showCheckMark)]
|
? [rawNode.render(rawNode, isSelected), renderCheckMark(showCheckMark)]
|
||||||
: [rawNode.label, renderCheckMark(showCheckMark)]
|
: [rawNode.label, renderCheckMark(showCheckMark)]
|
@ -96,7 +96,7 @@ export default cB('base-select-menu', `
|
|||||||
transition: color .3s var(--bezier);
|
transition: color .3s var(--bezier);
|
||||||
`, [
|
`, [
|
||||||
fadeInScaleUpTransition({
|
fadeInScaleUpTransition({
|
||||||
enterScale: 0.5
|
enterScale: '0.5'
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
]),
|
]),
|
@ -2,15 +2,16 @@ import { emptyDark } from '../../../empty/styles'
|
|||||||
import { scrollbarDark } from '../../../scrollbar/styles'
|
import { scrollbarDark } from '../../../scrollbar/styles'
|
||||||
import { commonDark } from '../../../_styles/new-common'
|
import { commonDark } from '../../../_styles/new-common'
|
||||||
import commonVariables from './_common'
|
import commonVariables from './_common'
|
||||||
|
import type { BaseSelectMenuTheme } from './light'
|
||||||
|
|
||||||
export default {
|
const baseSelectMenuDark: BaseSelectMenuTheme = {
|
||||||
name: 'BaseSelectMenu',
|
name: 'BaseSelectMenu',
|
||||||
common: commonDark,
|
common: commonDark,
|
||||||
peers: {
|
peers: {
|
||||||
Scrollbar: scrollbarDark,
|
Scrollbar: scrollbarDark,
|
||||||
Empty: emptyDark
|
Empty: emptyDark
|
||||||
},
|
},
|
||||||
getLocalVars (vars) {
|
self (vars) {
|
||||||
const {
|
const {
|
||||||
borderRadius,
|
borderRadius,
|
||||||
popoverColor,
|
popoverColor,
|
||||||
@ -42,3 +43,5 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default baseSelectMenuDark
|
@ -1,2 +1,3 @@
|
|||||||
export { default as baseSelectMenuLight } from './light'
|
export { default as baseSelectMenuLight } from './light'
|
||||||
export { default as baseSelectMenuDark } from './dark'
|
export { default as baseSelectMenuDark } from './dark'
|
||||||
|
export type { BaseSelectMenuThemeVars, BaseSelectMenuTheme } from './light'
|
@ -1,44 +0,0 @@
|
|||||||
import { emptyLight } from '../../../empty/styles'
|
|
||||||
import { scrollbarLight } from '../../../scrollbar/styles'
|
|
||||||
import { commonLight } from '../../../_styles/new-common'
|
|
||||||
import commonVariables from './_common'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'BaseSelectMenu',
|
|
||||||
common: commonLight,
|
|
||||||
peers: {
|
|
||||||
Scrollbar: scrollbarLight,
|
|
||||||
Empty: emptyLight
|
|
||||||
},
|
|
||||||
self (vars) {
|
|
||||||
const {
|
|
||||||
borderRadius,
|
|
||||||
popoverColor,
|
|
||||||
boxShadow2,
|
|
||||||
textColor3,
|
|
||||||
dividerColorOverlay,
|
|
||||||
textColor2,
|
|
||||||
primaryColorPressed,
|
|
||||||
textColorDisabled,
|
|
||||||
primaryColor,
|
|
||||||
opacityDisabled,
|
|
||||||
hoverColorOverlay
|
|
||||||
} = vars
|
|
||||||
return {
|
|
||||||
...commonVariables,
|
|
||||||
borderRadius: borderRadius,
|
|
||||||
color: popoverColor,
|
|
||||||
boxShadow: boxShadow2,
|
|
||||||
groupHeaderTextColor: textColor3,
|
|
||||||
actionDividerColor: dividerColorOverlay,
|
|
||||||
optionTextColor: textColor2,
|
|
||||||
optionTextColorPressed: primaryColorPressed,
|
|
||||||
optionTextColorDisabled: textColorDisabled,
|
|
||||||
optionTextColorActive: primaryColor,
|
|
||||||
optionOpacityDisabled: opacityDisabled,
|
|
||||||
optionCheckColor: primaryColor,
|
|
||||||
optionColorPending: hoverColorOverlay,
|
|
||||||
actionTextColor: textColor2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
53
src/_base/select-menu/styles/light.ts
Normal file
53
src/_base/select-menu/styles/light.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { emptyLight } from '../../../empty/styles'
|
||||||
|
import { scrollbarLight } from '../../../scrollbar/styles'
|
||||||
|
import { commonLight } from '../../../_styles/new-common'
|
||||||
|
import type { ThemeCommonVars } from '../../../_styles/new-common'
|
||||||
|
import commonVariables from './_common'
|
||||||
|
import { createTheme } from '../../../_mixins'
|
||||||
|
|
||||||
|
const self = (vars: ThemeCommonVars) => {
|
||||||
|
const {
|
||||||
|
borderRadius,
|
||||||
|
popoverColor,
|
||||||
|
boxShadow2,
|
||||||
|
textColor3,
|
||||||
|
dividerColorOverlay,
|
||||||
|
textColor2,
|
||||||
|
primaryColorPressed,
|
||||||
|
textColorDisabled,
|
||||||
|
primaryColor,
|
||||||
|
opacityDisabled,
|
||||||
|
hoverColorOverlay
|
||||||
|
} = vars
|
||||||
|
return {
|
||||||
|
...commonVariables,
|
||||||
|
borderRadius: borderRadius,
|
||||||
|
color: popoverColor,
|
||||||
|
boxShadow: boxShadow2,
|
||||||
|
groupHeaderTextColor: textColor3,
|
||||||
|
actionDividerColor: dividerColorOverlay,
|
||||||
|
optionTextColor: textColor2,
|
||||||
|
optionTextColorPressed: primaryColorPressed,
|
||||||
|
optionTextColorDisabled: textColorDisabled,
|
||||||
|
optionTextColorActive: primaryColor,
|
||||||
|
optionOpacityDisabled: opacityDisabled,
|
||||||
|
optionCheckColor: primaryColor,
|
||||||
|
optionColorPending: hoverColorOverlay,
|
||||||
|
actionTextColor: textColor2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BaseSelectMenuThemeVars = ReturnType<typeof self>
|
||||||
|
|
||||||
|
const baseSelectMenuLight = createTheme({
|
||||||
|
name: 'BaseSelectMenu',
|
||||||
|
common: commonLight,
|
||||||
|
peers: {
|
||||||
|
Scrollbar: scrollbarLight,
|
||||||
|
Empty: emptyLight
|
||||||
|
},
|
||||||
|
self
|
||||||
|
})
|
||||||
|
|
||||||
|
export default baseSelectMenuLight
|
||||||
|
export type BaseSelectMenuTheme = typeof baseSelectMenuLight
|
@ -20,7 +20,7 @@ import type { BaseSelectionTheme } from '../styles'
|
|||||||
import Suffix from './Suffix'
|
import Suffix from './Suffix'
|
||||||
import style from './styles/index.cssr'
|
import style from './styles/index.cssr'
|
||||||
|
|
||||||
interface Option {
|
export interface SelectOption {
|
||||||
value: string | number
|
value: string | number
|
||||||
label: string
|
label: string
|
||||||
}
|
}
|
||||||
@ -46,11 +46,11 @@ export default defineComponent({
|
|||||||
default: undefined
|
default: undefined
|
||||||
},
|
},
|
||||||
selectedOption: {
|
selectedOption: {
|
||||||
type: Object as PropType<Option | null>,
|
type: Object as PropType<SelectOption | null>,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
selectedOptions: {
|
selectedOptions: {
|
||||||
type: Array as PropType<Option[] | null>,
|
type: Array as PropType<SelectOption[] | null>,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
multiple: {
|
multiple: {
|
||||||
@ -184,7 +184,7 @@ export default defineComponent({
|
|||||||
const { onBlur } = props
|
const { onBlur } = props
|
||||||
if (onBlur) onBlur(e)
|
if (onBlur) onBlur(e)
|
||||||
}
|
}
|
||||||
function doDeleteOption (value: Option): void {
|
function doDeleteOption (value: SelectOption): void {
|
||||||
const { onDeleteOption } = props
|
const { onDeleteOption } = props
|
||||||
if (onDeleteOption) onDeleteOption(value)
|
if (onDeleteOption) onDeleteOption(value)
|
||||||
}
|
}
|
||||||
@ -220,7 +220,9 @@ export default defineComponent({
|
|||||||
// ', this may be a bug of naive-ui.'
|
// ', this may be a bug of naive-ui.'
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
if (e.relatedTarget && selfRef.value?.contains(e.relatedTarget as Node)) { return }
|
if (e.relatedTarget && selfRef.value?.contains(e.relatedTarget as Node)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
doBlur(e)
|
doBlur(e)
|
||||||
}
|
}
|
||||||
function handleClear (e: MouseEvent): void {
|
function handleClear (e: MouseEvent): void {
|
||||||
@ -248,7 +250,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleDeleteOption (option: Option): void {
|
function handleDeleteOption (option: SelectOption): void {
|
||||||
doDeleteOption(option)
|
doDeleteOption(option)
|
||||||
}
|
}
|
||||||
function handlePatternKeyDown (e: KeyboardEvent): void {
|
function handlePatternKeyDown (e: KeyboardEvent): void {
|
||||||
@ -343,6 +345,7 @@ export default defineComponent({
|
|||||||
borderActive,
|
borderActive,
|
||||||
arrowColor,
|
arrowColor,
|
||||||
arrowColorDisabled,
|
arrowColorDisabled,
|
||||||
|
loadingColor,
|
||||||
// form warning
|
// form warning
|
||||||
colorActiveWarning,
|
colorActiveWarning,
|
||||||
boxShadowFocusWarning,
|
boxShadowFocusWarning,
|
||||||
@ -393,6 +396,7 @@ export default defineComponent({
|
|||||||
'--text-color-disabled': textColorDisabled,
|
'--text-color-disabled': textColorDisabled,
|
||||||
'--arrow-color': arrowColor,
|
'--arrow-color': arrowColor,
|
||||||
'--arrow-color-disabled': arrowColorDisabled,
|
'--arrow-color-disabled': arrowColorDisabled,
|
||||||
|
'--loading-color': loadingColor,
|
||||||
// form warning
|
// form warning
|
||||||
'--color-active-warning': colorActiveWarning,
|
'--color-active-warning': colorActiveWarning,
|
||||||
'--box-shadow-focus-warning': boxShadowFocusWarning,
|
'--box-shadow-focus-warning': boxShadowFocusWarning,
|
||||||
|
@ -30,6 +30,7 @@ import {
|
|||||||
// --text-color
|
// --text-color
|
||||||
// --text-color-disabled
|
// --text-color-disabled
|
||||||
// --arrow-color
|
// --arrow-color
|
||||||
|
// --loading-color
|
||||||
// ...clear vars
|
// ...clear vars
|
||||||
// ...form item vars
|
// ...form item vars
|
||||||
export default c([
|
export default c([
|
||||||
@ -46,6 +47,9 @@ export default c([
|
|||||||
line-height: var(--height);
|
line-height: var(--height);
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
`, [
|
`, [
|
||||||
|
cB('base-loading', `
|
||||||
|
color: var(--loading-color);
|
||||||
|
`),
|
||||||
cB('base-selection-label', `
|
cB('base-selection-label', `
|
||||||
height: var(--height);
|
height: var(--height);
|
||||||
line-height: var(--height);
|
line-height: var(--height);
|
||||||
|
@ -48,6 +48,7 @@ const baseSelectionDark: BaseSelectionTheme = {
|
|||||||
caretColor: primaryColor,
|
caretColor: primaryColor,
|
||||||
arrowColor: iconColorOverlay,
|
arrowColor: iconColorOverlay,
|
||||||
arrowColorDisabled: iconColorDisabledOverlay,
|
arrowColorDisabled: iconColorDisabledOverlay,
|
||||||
|
loadingColor: primaryColor,
|
||||||
// warning
|
// warning
|
||||||
borderWarning: `1px solid ${warningColor}`,
|
borderWarning: `1px solid ${warningColor}`,
|
||||||
borderHoverWarning: `1px solid ${warningColorHover}`,
|
borderHoverWarning: `1px solid ${warningColorHover}`,
|
||||||
|
@ -2,6 +2,7 @@ import { changeColor, scaleColor } from 'seemly'
|
|||||||
import { commonLight } from '../../../_styles/new-common'
|
import { commonLight } from '../../../_styles/new-common'
|
||||||
import type { ThemeCommonVars } from '../../../_styles/new-common'
|
import type { ThemeCommonVars } from '../../../_styles/new-common'
|
||||||
import commonVariables from './_common'
|
import commonVariables from './_common'
|
||||||
|
import { createTheme } from '../../../_mixins'
|
||||||
|
|
||||||
const self = (vars: ThemeCommonVars) => {
|
const self = (vars: ThemeCommonVars) => {
|
||||||
const {
|
const {
|
||||||
@ -46,6 +47,7 @@ const self = (vars: ThemeCommonVars) => {
|
|||||||
caretColor: primaryColor,
|
caretColor: primaryColor,
|
||||||
arrowColor: iconColor,
|
arrowColor: iconColor,
|
||||||
arrowColorDisabled: iconColorDisabled,
|
arrowColorDisabled: iconColorDisabled,
|
||||||
|
loadingColor: primaryColor,
|
||||||
// warning
|
// warning
|
||||||
borderWarning: `1px solid ${warningColor}`,
|
borderWarning: `1px solid ${warningColor}`,
|
||||||
borderHoverWarning: `1px solid ${warningColorHover}`,
|
borderHoverWarning: `1px solid ${warningColorHover}`,
|
||||||
@ -82,11 +84,11 @@ const self = (vars: ThemeCommonVars) => {
|
|||||||
|
|
||||||
export type BaseSelectionThemeVars = ReturnType<typeof self>
|
export type BaseSelectionThemeVars = ReturnType<typeof self>
|
||||||
|
|
||||||
const baseSelectionLight = {
|
const baseSelectionLight = createTheme({
|
||||||
name: 'BaseSelection',
|
name: 'BaseSelection',
|
||||||
common: commonLight,
|
common: commonLight,
|
||||||
self
|
self
|
||||||
}
|
})
|
||||||
|
|
||||||
export default baseSelectionLight
|
export default baseSelectionLight
|
||||||
export type BaseSelectionTheme = typeof baseSelectionLight
|
export type BaseSelectionTheme = typeof baseSelectionLight
|
||||||
|
Loading…
Reference in New Issue
Block a user