vue-vben-admin/packages/effects/hooks/src/use-hover-toggle.ts

69 lines
2.0 KiB
TypeScript
Raw Normal View History

2025-05-02 22:08:36 +08:00
import type { Arrayable, MaybeElementRef } from '@vueuse/core';
import type { Ref } from 'vue';
import { computed, onUnmounted, ref, unref, watch } from 'vue';
import { isFunction } from '@vben/utils';
import { useElementHover } from '@vueuse/core';
/**
* true false
* @param refElement true
* @param delay
* @returns ref enable disable
*/
export function useHoverToggle(
refElement: Arrayable<MaybeElementRef>,
delay: (() => number) | number = 500,
) {
const isHovers: Array<Ref<boolean>> = [];
const value = ref(false);
const timer = ref<ReturnType<typeof setTimeout> | undefined>();
const refs = Array.isArray(refElement) ? refElement : [refElement];
refs.forEach((refEle) => {
const eleRef = computed(() => {
const ele = unref(refEle);
return ele instanceof Element ? ele : (ele?.$el as Element);
});
const isHover = useElementHover(eleRef);
isHovers.push(isHover);
});
const isOutsideAll = computed(() => isHovers.every((v) => !v.value));
function setValueDelay(val: boolean) {
timer.value && clearTimeout(timer.value);
timer.value = setTimeout(
() => {
value.value = val;
timer.value = undefined;
},
isFunction(delay) ? delay() : delay,
);
}
const watcher = watch(
isOutsideAll,
(val) => {
setValueDelay(!val);
},
{ immediate: true },
);
const controller = {
enable() {
watcher.resume();
},
disable() {
watcher.pause();
},
};
onUnmounted(() => {
timer.value && clearTimeout(timer.value);
});
return [value, controller] as [typeof value, typeof controller];
}