import { onMounted, ref, toRefs, computed, watch } from 'vue';
import type { Ref } from 'vue';
import { debounce } from 'lodash';
import { TooltipProps, BasePlacement, UseTooltipFn } from './tooltip-types';
export const transformOriginMap: Record<BasePlacement, string> = {
top: '50% calc(100% + 8px)',
bottom: '50% -8px',
left: 'calc(100% + 8px)',
right: '-8px 50%',
};
export function useTooltip(origin: Ref, props: TooltipProps): UseTooltipFn {
const { position, mouseEnterDelay, mouseLeaveDelay, enterable, disabled, hideAfter } = toRefs(props);
const visible = ref<boolean>(false);
const isEnter = ref<boolean>(false);
const positionArr = computed(() => (typeof position.value === 'string' ? [position.value] : position.value));
const placement = ref<BasePlacement>(positionArr.value[0]);
const overlayStyles = computed(() => ({
transformOrigin: transformOriginMap[placement.value],
}));
const enter = debounce(() => {
isEnter.value && (visible.value = true);
}, mouseEnterDelay.value);
const leave = debounce(() => {
!isEnter.value && (visible.value = false);
}, mouseLeaveDelay.value);
const onMouseenter = () => {
if (disabled.value) {
return;
}
isEnter.value = true;
enter();
};
const onMouseleave = () => {
isEnter.value = false;
leave();
};
const onPositionChange = (pos: BasePlacement) => {
placement.value = pos;
};
const quickLeave = () => {
isEnter.value = false;
visible.value = false;
};
const onMouseenterOverlay = () => {
if (!enterable.value) {
quickLeave();
} else {
onMouseenter();
}
};
onMounted(() => {
origin.value.addEventListener('mouseenter', onMouseenter);
origin.value.addEventListener('mouseleave', onMouseleave);
});
let timer: NodeJS.Timeout | null;
watch(visible, (newVal) => {
if (newVal && hideAfter.value) {
timer && clearTimeout(timer);
timer = setTimeout(quickLeave, hideAfter.value);
}
});
return {
visible,
placement,
positionArr,
overlayStyles,
onPositionChange,
onMouseenter,
onMouseleave,
onMouseenterOverlay,
};
}