@fesjs/fes-design
Version:
fes-design for PC
161 lines (158 loc) • 3.54 kB
JavaScript
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 };