element-plus/packages/hooks/use-popper/use-target-events.ts
JeremyWuuuuu a7a8f29a19 refactor(popper): use-popper-hook for popper
- Add new use popper hook into the codebase for replacing the current `use-popper`
2021-07-13 17:49:00 +08:00

92 lines
1.9 KiB
TypeScript

import { computed, getCurrentInstance } from 'vue'
import { isArray } from '@element-plus/utils/util'
export type TriggerType = 'click' | 'hover' | 'focus' | 'manual'
export type Trigger = TriggerType | TriggerType[]
export interface PopperEvents {
onClick?: (e: Event) => void
onMouseenter?: (e: Event) => void
onMouseleave?: (e: Event) => void
onFocus?: (e: Event) => void
onBlur?: (e: Event) => void
}
export const DEFAULT_TRIGGER = 'hover'
type Handler = () => void
export const useTargetEvents = (
onShow: Handler,
onHide: Handler,
onToggle: Handler,
) => {
const { props } = getCurrentInstance()
let triggerFocused = false
const popperEventsHandler = (e: Event) => {
e.stopPropagation()
switch (e.type) {
case 'click': {
if (triggerFocused) {
// reset previous focus event
triggerFocused = false
} else {
onToggle()
}
break
}
case 'mouseenter': {
onShow()
break
}
case 'mouseleave': {
onHide()
break
}
case 'focus': {
triggerFocused = true
onShow()
break
}
case 'blur': {
triggerFocused = false
onHide()
break
}
}
}
const triggerEventsMap: Partial<Record<
TriggerType,
(keyof PopperEvents)[]
>> = {
click: ['onClick'],
hover: ['onMouseenter', 'onMouseleave'],
focus: ['onFocus', 'onBlur'],
}
const mapEvents = (t: TriggerType) => {
const events = {} as PopperEvents
triggerEventsMap[t].forEach(event => {
events[event] = popperEventsHandler
})
return events
}
return computed(() => {
if (isArray(props.trigger)) {
return Object.values(props.trigger).reduce((pre, t) => {
return {
...pre,
...mapEvents(t),
}
}, {})
} else {
return mapEvents(props.trigger as TriggerType)
}
})
}