UNPKG

@fesjs/fes-design

Version:
161 lines (158 loc) 3.54 kB
import { ref, watch } from 'vue'; import { isBoolean, isFunction } from 'lodash-es'; const triggerEventsMap = { click: ['onClick'], hover: ['onMouseenter', 'onMouseleave'], focus: ['onFocus', 'onBlur'], contextmenu: ['onContextmenu', 'onClick'] }; function useTrigger(visible, updateVisible, props, updateVirtualRect) { let triggerFocused = false; let showTimer; let hideTimer; const events = ref({}); function clearTimers() { clearTimeout(showTimer); clearTimeout(hideTimer); } const hide = () => { const setHide = () => { if (props.onlyShowTrigger) { return; } if (isBoolean(props.disabled) && props.disabled) { return; } if (isFunction(props.disabled) && props.disabled()) { return; } updateVisible(false); }; clearTimers(); if (props.hideAfter) { hideTimer = setTimeout(() => { setHide(); }, props.hideAfter); } else { setHide(); } }; const show = () => { const setShow = () => { if (isBoolean(props.disabled) && props.disabled) { return; } if (isFunction(props.disabled) && props.disabled()) { return; } updateVisible(true); }; clearTimers(); if (props.showAfter) { showTimer = setTimeout(() => { setShow(); }, props.showAfter); } else { setShow(); } }; const toggleState = () => { if (visible.value) { hide(); } else { show(); } }; const popperEventsHandler = (e, t) => { // 不是用户触发的行为 e.stopPropagation(); switch (e.type) { case 'click': { if (t === 'contextmenu') { if (visible.value) { updateVirtualRect(null); toggleState(); } } else if (triggerFocused) { // reset previous focus event triggerFocused = false; } else { toggleState(); } break; } case 'mouseenter': { show(); break; } case 'mouseleave': { hide(); break; } case 'focus': { triggerFocused = true; show(); break; } case 'blur': { triggerFocused = false; hide(); break; } case 'contextmenu': { updateVirtualRect({ x: e.clientX, y: e.clientY }); e.preventDefault(); show(); break; } } }; const mapEvents = t => { const _events = {}; triggerEventsMap[t].forEach(event => { _events[event] = e => { popperEventsHandler(e, t); }; }); events.value = _events; }; watch(() => props.trigger, () => { if (props.trigger) { mapEvents(props.trigger); } }, { immediate: true }); function onPopperMouseEnter() { // if trigger is click, user won't be able to close popper when // user tries to move the mouse over popper contents if (props.trigger !== 'click') { clearTimeout(hideTimer); } } function onPopperMouseLeave() { const { trigger } = props; const shouldPrevent = trigger === 'click' || trigger === 'focus' || trigger === 'contextmenu'; if (shouldPrevent) { return; } hide(); } return { events, onPopperMouseEnter, onPopperMouseLeave }; } export { useTrigger as default };