mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
refactor(components): [popover] switch to script-setup syntax (#8273)
This commit is contained in:
@@ -2,7 +2,7 @@ import { nextTick, ref } from 'vue'
|
||||
import { afterEach, describe, expect, test } from 'vitest'
|
||||
import makeMount from '@element-plus/test-utils/make-mount'
|
||||
import { rAF } from '@element-plus/test-utils/tick'
|
||||
import Popover from '../src/index.vue'
|
||||
import Popover from '../src/popover.vue'
|
||||
import PopoverDirective, { VPopover } from '../src/directive'
|
||||
|
||||
const AXIOM = 'Rem is the best girl'
|
||||
|
||||
@@ -4,7 +4,7 @@ import { POPPER_CONTAINER_SELECTOR, useZIndex } from '@element-plus/hooks'
|
||||
import makeMount from '@element-plus/test-utils/make-mount'
|
||||
import { rAF } from '@element-plus/test-utils/tick'
|
||||
import { ElPopperTrigger } from '@element-plus/components/popper'
|
||||
import Popover from '../src/index.vue'
|
||||
import Popover from '../src/popover.vue'
|
||||
|
||||
const AXIOM = 'Rem is the best girl'
|
||||
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
import Popover from './src/index.vue'
|
||||
import { withInstall, withInstallDirective } from '@element-plus/utils'
|
||||
|
||||
import Popover from './src/popover.vue'
|
||||
import PopoverDirective, { VPopover } from './src/directive'
|
||||
|
||||
import type { App } from 'vue'
|
||||
import type { SFCWithInstall } from '@element-plus/utils'
|
||||
export const ElPopoverDirective = withInstallDirective(
|
||||
PopoverDirective,
|
||||
VPopover
|
||||
)
|
||||
|
||||
Popover.install = (app: App): void => {
|
||||
app.component(Popover.name, Popover)
|
||||
}
|
||||
;(PopoverDirective as SFCWithInstall<typeof PopoverDirective>).install = (
|
||||
app: App
|
||||
) => {
|
||||
app.directive(VPopover, PopoverDirective)
|
||||
}
|
||||
export const ElPopover = withInstall(Popover, {
|
||||
directive: ElPopoverDirective,
|
||||
})
|
||||
export default ElPopover
|
||||
|
||||
const _PopoverDirective = PopoverDirective as SFCWithInstall<
|
||||
typeof PopoverDirective
|
||||
>
|
||||
|
||||
Popover.directive = _PopoverDirective
|
||||
|
||||
const _Popover = Popover as any as SFCWithInstall<typeof Popover> & {
|
||||
directive: typeof _PopoverDirective
|
||||
}
|
||||
|
||||
export default _Popover
|
||||
export const ElPopover = _Popover
|
||||
export const ElPopoverDirective = _PopoverDirective
|
||||
export * from './src/popover'
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type ElPopover from './index.vue'
|
||||
import type { DirectiveBinding, ObjectDirective } from 'vue'
|
||||
import type { PopoverInstance } from './popover'
|
||||
|
||||
const attachEvents = (el: HTMLElement, binding: DirectiveBinding) => {
|
||||
const popperComponent: InstanceType<typeof ElPopover> =
|
||||
binding.arg || binding.value
|
||||
const popperComponent: PopoverInstance = binding.arg || binding.value
|
||||
const popover = popperComponent?.popperRef
|
||||
if (popover) {
|
||||
popover.triggerRef = el
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
<template>
|
||||
<el-tooltip
|
||||
ref="tooltipRef"
|
||||
v-bind="$attrs"
|
||||
:trigger="trigger"
|
||||
:placement="placement"
|
||||
:disabled="disabled"
|
||||
:visible="visible"
|
||||
:transition="transition"
|
||||
:popper-options="popperOptions"
|
||||
:tabindex="tabindex"
|
||||
:content="content"
|
||||
:offset="offset"
|
||||
:show-after="showAfter"
|
||||
:hide-after="hideAfter"
|
||||
:auto-close="autoClose"
|
||||
:show-arrow="showArrow"
|
||||
:aria-label="title"
|
||||
:effect="effect"
|
||||
:enterable="enterable"
|
||||
:popper-class="kls"
|
||||
:popper-style="style"
|
||||
:teleported="teleported"
|
||||
:persistent="persistent"
|
||||
:gpu-acceleration="gpuAcceleration"
|
||||
@before-show="beforeEnter"
|
||||
@before-hide="beforeLeave"
|
||||
@show="afterEnter"
|
||||
@hide="afterLeave"
|
||||
>
|
||||
<template v-if="$slots.reference">
|
||||
<slot name="reference" />
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<div v-if="title" :class="ns.e('title')" role="title">
|
||||
{{ title }}
|
||||
</div>
|
||||
<slot>
|
||||
{{ content }}
|
||||
</slot>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref, unref } from 'vue'
|
||||
import ElTooltip from '@element-plus/components/tooltip'
|
||||
import { isString } from '@element-plus/utils'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { usePopoverProps } from './popover'
|
||||
|
||||
import type { StyleValue } from 'vue'
|
||||
|
||||
const emits = [
|
||||
'update:visible',
|
||||
'before-enter',
|
||||
'before-leave',
|
||||
'after-enter',
|
||||
'after-leave',
|
||||
]
|
||||
|
||||
const COMPONENT_NAME = 'ElPopover'
|
||||
|
||||
export default defineComponent({
|
||||
name: COMPONENT_NAME,
|
||||
components: {
|
||||
ElTooltip,
|
||||
},
|
||||
props: usePopoverProps,
|
||||
emits,
|
||||
setup(props, { emit }) {
|
||||
const ns = useNamespace('popover')
|
||||
const tooltipRef = ref<InstanceType<typeof ElTooltip> | null>(null)
|
||||
const popperRef = computed(() => {
|
||||
return unref(tooltipRef)?.popperRef
|
||||
})
|
||||
const width = computed(() => {
|
||||
if (isString(props.width)) {
|
||||
return props.width as string
|
||||
}
|
||||
return `${props.width}px`
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
return [
|
||||
{
|
||||
width: width.value,
|
||||
},
|
||||
props.popperStyle,
|
||||
] as StyleValue
|
||||
})
|
||||
|
||||
const kls = computed(() => {
|
||||
return [ns.b(), props.popperClass, { [ns.m('plain')]: !!props.content }]
|
||||
})
|
||||
|
||||
const gpuAcceleration = computed(() => {
|
||||
return props.transition === 'el-fade-in-linear'
|
||||
})
|
||||
|
||||
const hide = () => {
|
||||
tooltipRef.value?.hide()
|
||||
}
|
||||
|
||||
const beforeEnter = () => {
|
||||
emit('before-enter')
|
||||
}
|
||||
const beforeLeave = () => {
|
||||
emit('before-leave')
|
||||
}
|
||||
|
||||
const afterEnter = () => {
|
||||
emit('after-enter')
|
||||
}
|
||||
|
||||
const afterLeave = () => {
|
||||
emit('update:visible', false)
|
||||
emit('after-leave')
|
||||
}
|
||||
|
||||
return {
|
||||
ns,
|
||||
kls,
|
||||
gpuAcceleration,
|
||||
style,
|
||||
tooltipRef,
|
||||
popperRef,
|
||||
hide,
|
||||
beforeEnter,
|
||||
beforeLeave,
|
||||
afterEnter,
|
||||
afterLeave,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -1,11 +1,13 @@
|
||||
import { buildProps } from '@element-plus/utils'
|
||||
import { buildProps, isBoolean } from '@element-plus/utils'
|
||||
import {
|
||||
useTooltipContentProps,
|
||||
useTooltipTriggerProps,
|
||||
} from '@element-plus/components/tooltip'
|
||||
import { dropdownProps } from '@element-plus/components/dropdown'
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import type Popover from './popover.vue'
|
||||
|
||||
export const usePopoverProps = buildProps({
|
||||
export const popoverProps = buildProps({
|
||||
trigger: useTooltipTriggerProps.trigger,
|
||||
placement: dropdownProps.placement,
|
||||
disabled: useTooltipTriggerProps.disabled,
|
||||
@@ -56,3 +58,15 @@ export const usePopoverProps = buildProps({
|
||||
default: true,
|
||||
},
|
||||
} as const)
|
||||
export type PopoverProps = ExtractPropTypes<typeof popoverProps>
|
||||
|
||||
export const popoverEmits = {
|
||||
'update:visible': (value: boolean) => isBoolean(value),
|
||||
'before-enter': () => true,
|
||||
'before-leave': () => true,
|
||||
'after-enter': () => true,
|
||||
'after-leave': () => true,
|
||||
}
|
||||
export type PopoverEmits = typeof popoverEmits
|
||||
|
||||
export type PopoverInstance = InstanceType<typeof Popover>
|
||||
|
||||
109
packages/components/popover/src/popover.vue
Normal file
109
packages/components/popover/src/popover.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<el-tooltip
|
||||
ref="tooltipRef"
|
||||
v-bind="$attrs"
|
||||
:trigger="trigger"
|
||||
:placement="placement"
|
||||
:disabled="disabled"
|
||||
:visible="visible"
|
||||
:transition="transition"
|
||||
:popper-options="popperOptions"
|
||||
:tabindex="tabindex"
|
||||
:content="content"
|
||||
:offset="offset"
|
||||
:show-after="showAfter"
|
||||
:hide-after="hideAfter"
|
||||
:auto-close="autoClose"
|
||||
:show-arrow="showArrow"
|
||||
:aria-label="title"
|
||||
:effect="effect"
|
||||
:enterable="enterable"
|
||||
:popper-class="kls"
|
||||
:popper-style="style"
|
||||
:teleported="teleported"
|
||||
:persistent="persistent"
|
||||
:gpu-acceleration="gpuAcceleration"
|
||||
@before-show="beforeEnter"
|
||||
@before-hide="beforeLeave"
|
||||
@show="afterEnter"
|
||||
@hide="afterLeave"
|
||||
>
|
||||
<template v-if="$slots.reference">
|
||||
<slot name="reference" />
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<div v-if="title" :class="ns.e('title')" role="title">
|
||||
{{ title }}
|
||||
</div>
|
||||
<slot>
|
||||
{{ content }}
|
||||
</slot>
|
||||
</template>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, unref } from 'vue'
|
||||
import { ElTooltip } from '@element-plus/components/tooltip'
|
||||
import { addUnit } from '@element-plus/utils'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { popoverEmits, popoverProps } from './popover'
|
||||
import type { TooltipInstance } from '@element-plus/components/tooltip'
|
||||
|
||||
defineOptions({
|
||||
name: 'ElPopover',
|
||||
})
|
||||
|
||||
const props = defineProps(popoverProps)
|
||||
const emit = defineEmits(popoverEmits)
|
||||
|
||||
const ns = useNamespace('popover')
|
||||
const tooltipRef = ref<TooltipInstance>()
|
||||
const popperRef = computed(() => {
|
||||
return unref(tooltipRef)?.popperRef
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
return [
|
||||
{
|
||||
width: addUnit(props.width),
|
||||
},
|
||||
props.popperStyle!,
|
||||
]
|
||||
})
|
||||
|
||||
const kls = computed(() => {
|
||||
return [ns.b(), props.popperClass!, { [ns.m('plain')]: !!props.content }]
|
||||
})
|
||||
|
||||
const gpuAcceleration = computed(() => {
|
||||
return props.transition === 'el-fade-in-linear'
|
||||
})
|
||||
|
||||
const hide = () => {
|
||||
tooltipRef.value?.hide()
|
||||
}
|
||||
|
||||
const beforeEnter = () => {
|
||||
emit('before-enter')
|
||||
}
|
||||
const beforeLeave = () => {
|
||||
emit('before-leave')
|
||||
}
|
||||
|
||||
const afterEnter = () => {
|
||||
emit('after-enter')
|
||||
}
|
||||
|
||||
const afterLeave = () => {
|
||||
emit('update:visible', false)
|
||||
emit('after-leave')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
/** @description popper ref */
|
||||
popperRef,
|
||||
/** @description hide popover */
|
||||
hide,
|
||||
})
|
||||
</script>
|
||||
@@ -30,6 +30,14 @@ export const withInstallFunction = <T>(fn: T, name: string) => {
|
||||
return fn as SFCInstallWithContext<T>
|
||||
}
|
||||
|
||||
export const withInstallDirective = <T>(directive: T, name: string) => {
|
||||
;(directive as SFCWithInstall<T>).install = (app: App): void => {
|
||||
app.directive(name, directive)
|
||||
}
|
||||
|
||||
return directive as SFCWithInstall<T>
|
||||
}
|
||||
|
||||
export const withNoopInstall = <T>(component: T) => {
|
||||
;(component as SFCWithInstall<T>).install = NOOP
|
||||
|
||||
|
||||
Reference in New Issue
Block a user