refactor(components): [popper] fix type error (#8529)

Co-authored-by: lizhequ <lizhequ@ysbang.cn>
This commit is contained in:
zz
2022-09-22 09:20:41 +08:00
committed by GitHub
parent b270dc1296
commit d73016155a
13 changed files with 148 additions and 77 deletions

View File

@@ -16,6 +16,3 @@ export * from './src/content'
export * from './src/arrow'
export type { Placement, Options } from '@popperjs/core'
export type ElPopperArrowInstance = InstanceType<typeof ElPopperArrow>
export type ElPopperArrowTrigger = InstanceType<typeof ElPopperTrigger>
export type ElPopperArrowContent = InstanceType<typeof ElPopperContent>

View File

@@ -1,12 +1,23 @@
import { buildProps } from '@element-plus/utils'
import type { ExtractPropTypes } from 'vue'
import type Arrow from './arrow.vue'
export const usePopperArrowProps = buildProps({
export const popperArrowProps = buildProps({
arrowOffset: {
type: Number,
default: 5,
},
} as const)
export type PopperArrowProps = ExtractPropTypes<typeof popperArrowProps>
export type UsePopperArrowProps = ExtractPropTypes<typeof usePopperArrowProps>
export type PopperArrowInstance = InstanceType<typeof Arrow>
/** @deprecated use `popperArrowProps` instead, and it will be deprecated in the next major version */
export const usePopperArrowProps = popperArrowProps
/** @deprecated use `PopperArrowProps` instead, and it will be deprecated in the next major version */
export type UsePopperArrowProps = PopperArrowProps
/** @deprecated use `PopperArrowInstance` instead, and it will be deprecated in the next major version */
export type ElPopperArrowInstance = PopperArrowInstance

View File

@@ -6,14 +6,14 @@
import { inject, onBeforeUnmount, watch } from 'vue'
import { useNamespace } from '@element-plus/hooks'
import { POPPER_CONTENT_INJECTION_KEY } from '@element-plus/tokens'
import { usePopperArrowProps } from './arrow'
import { popperArrowProps } from './arrow'
defineOptions({
name: 'ElPopperArrow',
inheritAttrs: false,
})
const props = defineProps(usePopperArrowProps)
const props = defineProps(popperArrowProps)
const ns = useNamespace('popper')
const { arrowOffset, arrowRef } = inject(

View File

@@ -3,12 +3,21 @@ import { buildProps, definePropType } from '@element-plus/utils'
import type { ExtractPropTypes, StyleValue } from 'vue'
import type { Options, Placement } from '@popperjs/core'
import type { Measurable } from '@element-plus/tokens'
import type Content from './content.vue'
type ClassObjectType = Record<string, boolean>
type ClassType = string | ClassObjectType | ClassType[]
const POSITIONING_STRATEGIES = ['fixed', 'absolute'] as const
export const usePopperCoreConfigProps = buildProps({
export interface CreatePopperInstanceParams {
referenceEl: Measurable
popperContentEl: HTMLElement
arrowEl: HTMLElement | undefined
}
export const popperCoreConfigProps = buildProps({
boundariesPadding: {
type: Number,
default: 0,
@@ -40,12 +49,19 @@ export const usePopperCoreConfigProps = buildProps({
default: 'absolute',
},
} as const)
export type PopperCoreConfigProps = ExtractPropTypes<
typeof popperCoreConfigProps
>
export const usePopperContentProps = buildProps({
...usePopperCoreConfigProps,
export const popperContentProps = buildProps({
...popperCoreConfigProps,
id: String,
style: { type: definePropType<StyleValue>([String, Array, Object]) },
className: { type: definePropType<ClassType>([String, Array, Object]) },
style: {
type: definePropType<StyleValue>([String, Array, Object]),
},
className: {
type: definePropType<ClassType>([String, Array, Object]),
},
effect: {
type: String,
default: 'dark',
@@ -87,19 +103,33 @@ export const usePopperContentProps = buildProps({
virtualTriggering: Boolean,
zIndex: Number,
} as const)
export type PopperContentProps = ExtractPropTypes<typeof popperContentProps>
export const usePopperContentEmits = [
'mouseenter',
'mouseleave',
'focus',
'blur',
'close',
]
export const popperContentEmits = {
mouseenter: (evt: MouseEvent) => evt instanceof MouseEvent,
mouseleave: (evt: MouseEvent) => evt instanceof MouseEvent,
focus: () => true,
blur: () => true,
close: () => true,
}
export type PopperContentEmits = typeof popperContentEmits
export type UsePopperContentProps = ExtractPropTypes<
typeof usePopperContentProps
>
export type PopperContentInstance = InstanceType<typeof Content>
export type UsePopperCoreConfigProps = ExtractPropTypes<
typeof usePopperCoreConfigProps
>
/** @deprecated use `popperCoreConfigProps` instead, and it will be deprecated in the next major version */
export const usePopperCoreConfigProps = popperCoreConfigProps
/** @deprecated use `popperContentProps` instead, and it will be deprecated in the next major version */
export const usePopperContentProps = popperContentProps
/** @deprecated use `popperContentEmits` instead, and it will be deprecated in the next major version */
export const usePopperContentEmits = popperContentEmits
/** @deprecated use `PopperCoreConfigProps` instead, and it will be deprecated in the next major version */
export type UsePopperCoreConfigProps = PopperCoreConfigProps
/** @deprecated use `PopperContentProps` instead, and it will be deprecated in the next major version */
export type UsePopperContentProps = PopperContentProps
/** @deprecated use `PopperContentInstance` instead, and it will be deprecated in the next major version */
export type ElPopperArrowContent = PopperContentInstance

View File

@@ -24,7 +24,6 @@
</template>
<script lang="ts" setup>
// @ts-nocheck
import {
computed,
inject,
@@ -32,7 +31,6 @@ import {
onMounted,
provide,
ref,
toRefs,
unref,
watch,
} from 'vue'
@@ -47,18 +45,19 @@ import {
formItemContextKey,
} from '@element-plus/tokens'
import { isElement } from '@element-plus/utils'
import { usePopperContentEmits, usePopperContentProps } from './content'
import { popperContentEmits, popperContentProps } from './content'
import { buildPopperOptions, unwrapMeasurableEl } from './utils'
import type { WatchStopHandle } from 'vue'
import type { CreatePopperInstanceParams } from './content'
defineOptions({
name: 'ElPopperContent',
})
const emit = defineEmits(usePopperContentEmits)
const emit = defineEmits(popperContentEmits)
const props = defineProps(usePopperContentProps)
const props = defineProps(popperContentProps)
const { popperInstanceRef, contentRef, triggerRef, role } = inject(
POPPER_INJECTION_KEY,
@@ -68,7 +67,7 @@ const formItemContext = inject(formItemContextKey, undefined)
const { nextZIndex } = useZIndex()
const ns = useNamespace('popper')
const popperContentRef = ref<HTMLElement>()
const focusStartRef = ref<string | HTMLElement>('first')
const focusStartRef = ref<'container' | 'first' | HTMLElement>('first')
const arrowRef = ref<HTMLElement>()
const arrowOffset = ref<number>()
provide(POPPER_CONTENT_INJECTION_KEY, {
@@ -112,7 +111,11 @@ const ariaModal = computed<string | undefined>(() => {
return role && role.value === 'dialog' ? 'false' : undefined
})
const createPopperInstance = ({ referenceEl, popperContentEl, arrowEl }) => {
const createPopperInstance = ({
referenceEl,
popperContentEl,
arrowEl,
}: CreatePopperInstanceParams) => {
const options = buildPopperOptions(props, {
arrowEl,
arrowOffset: unref(arrowOffset),
@@ -216,14 +219,13 @@ onMounted(() => {
const prevEl = unref(prevTriggerTargetEl || popperContentRef.value)
if (isElement(el)) {
const { ariaLabel, id } = toRefs(props)
triggerTargetAriaStopWatch = watch(
[role, ariaLabel, ariaModal, id],
[role, () => props.ariaLabel, ariaModal, () => props.id],
(watches) => {
;['role', 'aria-label', 'aria-modal', 'id'].forEach((key, idx) => {
isNil(watches[idx])
? el.removeAttribute(key)
: el.setAttribute(key, watches[idx])
: el.setAttribute(key, watches[idx]!)
})
},
{ immediate: true }

View File

@@ -1,6 +1,7 @@
import { buildProps } from '@element-plus/utils'
import type { ExtractPropTypes } from 'vue'
import type Popper from './popper.vue'
const effects = ['light', 'dark'] as const
const triggers = ['click', 'contextmenu', 'hover', 'focus'] as const
@@ -24,7 +25,7 @@ export const roleTypes = [
export type PopperEffect = typeof effects[number]
export type PopperTrigger = typeof triggers[number]
export const usePopperProps = buildProps({
export const popperProps = buildProps({
role: {
type: String,
values: roleTypes,
@@ -32,4 +33,12 @@ export const usePopperProps = buildProps({
},
} as const)
export type UsePopperProps = ExtractPropTypes<typeof usePopperProps>
export type PopperProps = ExtractPropTypes<typeof popperProps>
export type PopperInstance = InstanceType<typeof Popper>
/** @deprecated use `popperProps` instead, and it will be deprecated in the next major version */
export const usePopperProps = popperProps
/** @deprecated use `PopperProps` instead, and it will be deprecated in the next major version */
export type UsePopperProps = PopperProps

View File

@@ -5,7 +5,7 @@
<script lang="ts" setup>
import { computed, provide, ref } from 'vue'
import { POPPER_INJECTION_KEY } from '@element-plus/tokens'
import { usePopperProps } from './popper'
import { popperProps } from './popper'
import type { Instance as PopperInstance } from '@popperjs/core'
import type { ElPopperInjectionContext } from '@element-plus/tokens'
@@ -14,7 +14,7 @@ defineOptions({
name: 'ElPopperRoot',
inheritAttrs: false,
})
const props = defineProps(usePopperProps)
const props = defineProps(popperProps)
const triggerRef = ref<HTMLElement>()
const popperInstanceRef = ref<PopperInstance>()

View File

@@ -1,20 +1,44 @@
import { buildProps, definePropType } from '@element-plus/utils'
import type { Measurable } from '@element-plus/tokens'
export const usePopperTriggerProps = buildProps({
import type { Measurable } from '@element-plus/tokens'
import type Trigger from './trigger.vue'
export const popperTriggerProps = buildProps({
virtualRef: {
type: definePropType<Measurable>(Object),
},
virtualTriggering: Boolean,
onMouseenter: Function,
onMouseleave: Function,
onClick: Function,
onKeydown: Function,
onFocus: Function,
onBlur: Function,
onContextmenu: Function,
onMouseenter: {
type: definePropType<(e: Event) => void>(Function),
},
onMouseleave: {
type: definePropType<(e: Event) => void>(Function),
},
onClick: {
type: definePropType<(e: Event) => void>(Function),
},
onKeydown: {
type: definePropType<(e: Event) => void>(Function),
},
onFocus: {
type: definePropType<(e: Event) => void>(Function),
},
onBlur: {
type: definePropType<(e: Event) => void>(Function),
},
onContextmenu: {
type: definePropType<(e: Event) => void>(Function),
},
id: String,
open: Boolean,
} as const)
export type PopperTriggerProps = typeof usePopperTriggerProps
export type PopperTriggerProps = typeof popperTriggerProps
export type PopperTriggerInstance = InstanceType<typeof Trigger>
/** @deprecated use `popperTriggerProps` instead, and it will be deprecated in the next major version */
export const usePopperTriggerProps = popperTriggerProps
/** @deprecated use `PopperTriggerInstance` instead, and it will be deprecated in the next major version */
export type ElPopperArrowTrigger = PopperTriggerInstance

View File

@@ -12,7 +12,6 @@
</template>
<script lang="ts" setup>
// @ts-nocheck
import { computed, inject, onBeforeUnmount, onMounted, watch } from 'vue'
import { isNil } from 'lodash-unified'
import { unrefElement } from '@vueuse/core'
@@ -20,7 +19,7 @@ import { ElOnlyChild } from '@element-plus/components/slot'
import { useForwardRef } from '@element-plus/hooks'
import { POPPER_INJECTION_KEY } from '@element-plus/tokens'
import { isElement } from '@element-plus/utils'
import { usePopperTriggerProps } from './trigger'
import { popperTriggerProps } from './trigger'
import type { WatchStopHandle } from 'vue'
@@ -29,7 +28,7 @@ defineOptions({
inheritAttrs: false,
})
const props = defineProps(usePopperTriggerProps)
const props = defineProps(popperTriggerProps)
const { role, triggerRef } = inject(POPPER_INJECTION_KEY, undefined)!
@@ -73,20 +72,22 @@ onMounted(() => {
)
watch(
() => triggerRef.value,
triggerRef,
(el, prevEl) => {
virtualTriggerAriaStopWatch?.()
virtualTriggerAriaStopWatch = undefined
if (isElement(el)) {
;[
'onMouseenter',
'onMouseleave',
'onClick',
'onKeydown',
'onFocus',
'onBlur',
'onContextmenu',
].forEach((eventName) => {
;(
[
'onMouseenter',
'onMouseleave',
'onClick',
'onKeydown',
'onFocus',
'onBlur',
'onContextmenu',
] as const
).forEach((eventName) => {
const handler = props[eventName]
if (handler) {
;(el as HTMLElement).addEventListener(
@@ -110,7 +111,7 @@ onMounted(() => {
].forEach((key, idx) => {
isNil(watches[idx])
? el.removeAttribute(key)
: el.setAttribute(key, watches[idx])
: el.setAttribute(key, watches[idx]!)
})
},
{ immediate: true }

View File

@@ -3,7 +3,7 @@ import { isClient, unrefElement } from '@vueuse/core'
import type { ComponentPublicInstance } from 'vue'
import type { MaybeRef } from '@vueuse/core'
import type { Measurable } from '@element-plus/tokens'
import type { UsePopperCoreConfigProps } from './content'
import type { PopperCoreConfigProps } from './content'
type ArrowProps = {
arrowEl: HTMLElement | undefined
@@ -11,7 +11,7 @@ type ArrowProps = {
}
export const buildPopperOptions = (
props: UsePopperCoreConfigProps,
props: PopperCoreConfigProps,
arrowProps: ArrowProps
) => {
const { placement, strategy, popperOptions } = props
@@ -34,7 +34,7 @@ export const unwrapMeasurableEl = (
return unrefElement($el as HTMLElement)
}
function genModifiers(options: UsePopperCoreConfigProps) {
function genModifiers(options: PopperCoreConfigProps) {
const { offset, gpuAcceleration, fallbackPlacements } = options
return [
{
@@ -83,7 +83,7 @@ function attachArrow(options: any, { arrowEl, arrowOffset }: ArrowProps) {
function deriveExtraModifiers(
options: any,
modifiers: UsePopperCoreConfigProps['popperOptions']['modifiers']
modifiers: PopperCoreConfigProps['popperOptions']['modifiers']
) {
if (modifiers) {
options.modifiers = [...options.modifiers, ...(modifiers ?? [])]

View File

@@ -1,5 +1,5 @@
import { buildProps, definePropType } from '@element-plus/utils'
import { usePopperContentProps } from '@element-plus/components/popper'
import { popperContentProps } from '@element-plus/components/popper'
import {
POPPER_CONTAINER_SELECTOR,
useDelayedToggleProps,
@@ -11,7 +11,7 @@ const ns = useNamespace('tooltip')
export const useTooltipContentProps = buildProps({
...useDelayedToggleProps,
...usePopperContentProps,
...popperContentProps,
appendTo: {
type: definePropType<string | HTMLElement>([String, Object]),
default: POPPER_CONTAINER_SELECTOR,

View File

@@ -1,9 +1,6 @@
import { buildProps } from '@element-plus/utils'
import { createModelToggleComposable } from '@element-plus/hooks'
import {
usePopperArrowProps,
usePopperProps,
} from '@element-plus/components/popper'
import { popperArrowProps, popperProps } from '@element-plus/components/popper'
import { useTooltipContentProps } from './content'
import { useTooltipTriggerProps } from './trigger'
import type Tooltip from './tooltip.vue'
@@ -17,11 +14,11 @@ export const {
} = createModelToggleComposable('visible' as const)
export const useTooltipProps = buildProps({
...usePopperProps,
...popperProps,
...useTooltipModelToggleProps,
...useTooltipContentProps,
...useTooltipTriggerProps,
...usePopperArrowProps,
...popperArrowProps,
openDelay: {
type: Number,
},

View File

@@ -1,5 +1,5 @@
import { buildProps, definePropType } from '@element-plus/utils'
import { usePopperTriggerProps } from '@element-plus/components/popper'
import { popperTriggerProps } from '@element-plus/components/popper'
import { EVENT_CODE } from '@element-plus/constants'
import type { Arrayable } from '@element-plus/utils'
import type { ExtractPropTypes } from 'vue'
@@ -7,7 +7,7 @@ import type { ExtractPropTypes } from 'vue'
export type TooltipTriggerType = 'hover' | 'focus' | 'click' | 'contextmenu'
export const useTooltipTriggerProps = buildProps({
...usePopperTriggerProps,
...popperTriggerProps,
disabled: Boolean,
trigger: {
type: definePropType<Arrayable<TooltipTriggerType>>([String, Array]),