2020-11-04 11:24:36 +08:00
|
|
|
<template>
|
2022-02-11 10:51:38 +08:00
|
|
|
<div :class="ns.b()">
|
2022-01-04 09:15:15 +08:00
|
|
|
<el-tooltip
|
|
|
|
ref="popperRef"
|
2021-11-05 15:33:17 +08:00
|
|
|
:effect="effect"
|
2022-01-16 13:56:16 +08:00
|
|
|
:fallback-placements="['bottom', 'top']"
|
|
|
|
:popper-options="popperOptions"
|
2022-01-04 09:15:15 +08:00
|
|
|
:gpu-acceleration="false"
|
|
|
|
:hide-after="hideTimeout"
|
2021-11-05 15:33:17 +08:00
|
|
|
:manual-mode="true"
|
2022-01-04 09:15:15 +08:00
|
|
|
:placement="placement"
|
2022-02-11 10:51:38 +08:00
|
|
|
:popper-class="[ns.e('popper'), popperClass]"
|
2022-01-04 09:15:15 +08:00
|
|
|
:reference-element="referenceElementRef?.$el"
|
|
|
|
:trigger="trigger"
|
|
|
|
:show-after="showTimeout"
|
|
|
|
:stop-popper-mouse-event="false"
|
|
|
|
:virtual-ref="triggeringElementRef"
|
|
|
|
:virtual-triggering="splitButton"
|
2021-11-05 15:33:17 +08:00
|
|
|
append-to-body
|
2022-01-04 09:15:15 +08:00
|
|
|
pure
|
2022-02-11 10:51:38 +08:00
|
|
|
:transition="`${ns.namespace.value}zoom-in-top`"
|
2022-01-09 17:38:51 +08:00
|
|
|
persistent
|
2022-01-04 09:15:15 +08:00
|
|
|
@show="$emit('visible-change', true)"
|
|
|
|
@hide="$emit('visible-change', false)"
|
2021-11-05 15:33:17 +08:00
|
|
|
>
|
2022-01-04 09:15:15 +08:00
|
|
|
<template #content>
|
2021-11-05 15:33:17 +08:00
|
|
|
<el-scrollbar
|
|
|
|
ref="scrollbar"
|
|
|
|
:wrap-style="wrapStyle"
|
2022-01-04 09:15:15 +08:00
|
|
|
tag="ul"
|
2022-02-11 10:51:38 +08:00
|
|
|
:view-class="ns.e('list')"
|
2021-11-05 15:33:17 +08:00
|
|
|
>
|
2022-01-04 09:15:15 +08:00
|
|
|
<el-focus-trap trapped @mount-on-focus="onMountOnFocus">
|
|
|
|
<el-roving-focus-group
|
|
|
|
:loop="loop"
|
|
|
|
:current-tab-id="currentTabId"
|
|
|
|
orientation="horizontal"
|
|
|
|
@current-tab-id-change="handleCurrentTabIdChange"
|
|
|
|
@entry-focus="handleEntryFocus"
|
|
|
|
>
|
|
|
|
<el-dropdown-collection>
|
|
|
|
<slot name="dropdown"></slot>
|
|
|
|
</el-dropdown-collection>
|
|
|
|
</el-roving-focus-group>
|
|
|
|
</el-focus-trap>
|
2021-11-05 15:33:17 +08:00
|
|
|
</el-scrollbar>
|
|
|
|
</template>
|
2022-01-04 09:15:15 +08:00
|
|
|
<template v-if="!splitButton" #default>
|
|
|
|
<div :class="dropdownTriggerKls">
|
|
|
|
<slot name="default" />
|
2021-11-05 15:33:17 +08:00
|
|
|
</div>
|
|
|
|
</template>
|
2022-01-04 09:15:15 +08:00
|
|
|
</el-tooltip>
|
|
|
|
<template v-if="splitButton">
|
|
|
|
<el-button-group>
|
|
|
|
<el-button
|
|
|
|
ref="referenceElementRef"
|
|
|
|
:size="dropdownSize"
|
|
|
|
:type="type"
|
|
|
|
@click="handlerMainButtonClick"
|
|
|
|
>
|
|
|
|
<slot name="default" />
|
|
|
|
</el-button>
|
|
|
|
<el-button
|
|
|
|
ref="triggeringElementRef"
|
|
|
|
:size="dropdownSize"
|
|
|
|
:type="type"
|
2022-02-11 10:51:38 +08:00
|
|
|
:class="ns.e('caret-button')"
|
2022-01-04 09:15:15 +08:00
|
|
|
>
|
2022-02-11 10:51:38 +08:00
|
|
|
<el-icon :class="ns.e('icon')"><arrow-down /></el-icon>
|
2022-01-04 09:15:15 +08:00
|
|
|
</el-button>
|
|
|
|
</el-button-group>
|
|
|
|
</template>
|
2021-11-05 15:33:17 +08:00
|
|
|
</div>
|
2020-11-04 11:24:36 +08:00
|
|
|
</template>
|
2020-11-12 14:43:55 +08:00
|
|
|
<script lang="ts">
|
2020-08-28 11:44:04 +08:00
|
|
|
import {
|
2022-01-04 09:15:15 +08:00
|
|
|
computed,
|
2020-08-28 11:44:04 +08:00
|
|
|
defineComponent,
|
|
|
|
getCurrentInstance,
|
2022-01-04 09:15:15 +08:00
|
|
|
provide,
|
2020-08-28 11:44:04 +08:00
|
|
|
ref,
|
2022-01-04 09:15:15 +08:00
|
|
|
toRef,
|
|
|
|
unref,
|
2020-08-28 11:44:04 +08:00
|
|
|
} from 'vue'
|
2021-08-24 13:36:48 +08:00
|
|
|
import ElButton from '@element-plus/components/button'
|
2022-01-04 09:15:15 +08:00
|
|
|
import ElTooltip from '@element-plus/components/tooltip'
|
2021-08-24 13:36:48 +08:00
|
|
|
import ElScrollbar from '@element-plus/components/scrollbar'
|
2021-10-28 23:37:26 +08:00
|
|
|
import ElIcon from '@element-plus/components/icon'
|
2022-01-04 09:15:15 +08:00
|
|
|
import ElFocusTrap from '@element-plus/components/focus-trap'
|
|
|
|
import ElRovingFocusGroup from '@element-plus/components/roving-focus-group'
|
2022-02-11 11:03:15 +08:00
|
|
|
import { addUnit } from '@element-plus/utils'
|
2021-12-04 11:20:06 +08:00
|
|
|
import { ArrowDown } from '@element-plus/icons-vue'
|
2022-02-11 10:51:38 +08:00
|
|
|
import { useNamespace, useSize } from '@element-plus/hooks'
|
2022-01-04 09:15:15 +08:00
|
|
|
import { ElCollection as ElDropdownCollection, dropdownProps } from './dropdown'
|
|
|
|
import { DROPDOWN_INJECTION_KEY } from './tokens'
|
2021-10-27 23:17:13 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
import type { CSSProperties } from 'vue'
|
2020-08-28 11:44:04 +08:00
|
|
|
|
2021-08-24 13:36:48 +08:00
|
|
|
const { ButtonGroup: ElButtonGroup } = ElButton
|
2021-08-04 18:28:08 +08:00
|
|
|
|
2020-08-28 11:44:04 +08:00
|
|
|
export default defineComponent({
|
|
|
|
name: 'ElDropdown',
|
|
|
|
components: {
|
|
|
|
ElButton,
|
2022-01-04 09:15:15 +08:00
|
|
|
ElFocusTrap,
|
2020-08-28 11:44:04 +08:00
|
|
|
ElButtonGroup,
|
2021-02-08 15:14:01 +08:00
|
|
|
ElScrollbar,
|
2022-01-04 09:15:15 +08:00
|
|
|
ElDropdownCollection,
|
|
|
|
ElTooltip,
|
|
|
|
ElRovingFocusGroup,
|
2021-10-27 23:17:13 +08:00
|
|
|
ElIcon,
|
|
|
|
ArrowDown,
|
2020-08-28 11:44:04 +08:00
|
|
|
},
|
2022-01-04 09:15:15 +08:00
|
|
|
props: dropdownProps,
|
2020-08-28 11:44:04 +08:00
|
|
|
emits: ['visible-change', 'click', 'command'],
|
2020-11-04 11:24:36 +08:00
|
|
|
setup(props, { emit }) {
|
2020-08-28 11:44:04 +08:00
|
|
|
const _instance = getCurrentInstance()
|
2022-02-11 10:51:38 +08:00
|
|
|
const ns = useNamespace('dropdown')
|
2020-08-28 11:44:04 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
const triggeringElementRef = ref()
|
|
|
|
const referenceElementRef = ref()
|
|
|
|
const popperRef = ref<InstanceType<typeof ElTooltip> | null>(null)
|
|
|
|
const contentRef = ref<HTMLElement | null>(null)
|
2021-02-08 15:14:01 +08:00
|
|
|
const scrollbar = ref(null)
|
2022-01-04 09:15:15 +08:00
|
|
|
const currentTabId = ref<string | null>(null)
|
|
|
|
const isUsingKeyboard = ref(false)
|
|
|
|
|
2021-11-12 06:46:13 +08:00
|
|
|
const wrapStyle = computed<CSSProperties>(() => ({
|
|
|
|
maxHeight: addUnit(props.maxHeight),
|
|
|
|
}))
|
2022-02-11 10:51:38 +08:00
|
|
|
const dropdownTriggerKls = computed(() => [ns.m(dropdownSize.value)])
|
2020-08-28 11:44:04 +08:00
|
|
|
|
|
|
|
function handleClick() {
|
2022-01-19 15:04:44 +08:00
|
|
|
handleClose()
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleClose() {
|
2022-01-04 09:15:15 +08:00
|
|
|
popperRef.value?.onClose()
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
|
|
|
|
2022-01-19 15:04:44 +08:00
|
|
|
function handleOpen() {
|
|
|
|
popperRef.value?.onOpen()
|
|
|
|
}
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
const dropdownSize = useSize()
|
2020-08-28 11:44:04 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
function commandHandler(...args: any[]) {
|
|
|
|
emit('command', ...args)
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
function onItemEnter() {
|
|
|
|
// NOOP for now
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
function onItemLeave() {
|
|
|
|
const contentEl = unref(contentRef)
|
2020-08-28 11:44:04 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
contentEl?.focus()
|
|
|
|
currentTabId.value = null
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
2021-02-08 15:14:01 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
function handleCurrentTabIdChange(id: string) {
|
|
|
|
currentTabId.value = id
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
function handleEntryFocus(e: Event) {
|
|
|
|
if (!isUsingKeyboard.value) {
|
|
|
|
e.preventDefault()
|
|
|
|
e.stopImmediatePropagation()
|
|
|
|
}
|
2020-08-28 11:44:04 +08:00
|
|
|
}
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
provide(DROPDOWN_INJECTION_KEY, {
|
|
|
|
contentRef,
|
|
|
|
isUsingKeyboard,
|
|
|
|
onItemEnter,
|
|
|
|
onItemLeave,
|
|
|
|
})
|
|
|
|
|
2020-08-28 11:44:04 +08:00
|
|
|
provide('elDropdown', {
|
|
|
|
instance: _instance,
|
|
|
|
dropdownSize,
|
|
|
|
handleClick,
|
|
|
|
commandHandler,
|
2022-01-04 09:15:15 +08:00
|
|
|
trigger: toRef(props, 'trigger'),
|
|
|
|
hideOnClick: toRef(props, 'hideOnClick'),
|
2020-08-28 11:44:04 +08:00
|
|
|
})
|
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
const onMountOnFocus = (e: Event) => {
|
|
|
|
e.preventDefault()
|
|
|
|
contentRef.value?.focus?.({
|
|
|
|
preventScroll: true,
|
2020-11-04 11:24:36 +08:00
|
|
|
})
|
2022-01-04 09:15:15 +08:00
|
|
|
}
|
2020-08-28 11:44:04 +08:00
|
|
|
|
2022-01-04 09:15:15 +08:00
|
|
|
const handlerMainButtonClick = (event: MouseEvent) => {
|
2020-08-28 11:44:04 +08:00
|
|
|
emit('click', event)
|
|
|
|
}
|
|
|
|
|
2020-11-04 11:24:36 +08:00
|
|
|
return {
|
2022-02-11 10:51:38 +08:00
|
|
|
ns,
|
2021-02-08 15:14:01 +08:00
|
|
|
scrollbar,
|
|
|
|
wrapStyle,
|
2022-01-04 09:15:15 +08:00
|
|
|
dropdownTriggerKls,
|
2020-11-04 11:24:36 +08:00
|
|
|
dropdownSize,
|
2022-01-04 09:15:15 +08:00
|
|
|
currentTabId,
|
|
|
|
handleCurrentTabIdChange,
|
2020-11-04 11:24:36 +08:00
|
|
|
handlerMainButtonClick,
|
2022-01-04 09:15:15 +08:00
|
|
|
handleEntryFocus,
|
2022-01-19 15:04:44 +08:00
|
|
|
handleClose,
|
|
|
|
handleOpen,
|
2022-01-04 09:15:15 +08:00
|
|
|
onMountOnFocus,
|
|
|
|
popperRef,
|
|
|
|
triggeringElementRef,
|
|
|
|
referenceElementRef,
|
2020-11-04 11:24:36 +08:00
|
|
|
}
|
2020-08-28 11:44:04 +08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
</script>
|