diff --git a/packages/editor/src/hooks/use-float-box.ts b/packages/editor/src/hooks/use-float-box.ts index 13da788f..c212d64a 100644 --- a/packages/editor/src/hooks/use-float-box.ts +++ b/packages/editor/src/hooks/use-float-box.ts @@ -1,4 +1,4 @@ -import { computed, ComputedRef, inject, ref, watch } from 'vue'; +import { computed, ComputedRef, inject, onBeforeUnmount, ref, watch } from 'vue'; import type { Services } from '@editor/type'; @@ -30,22 +30,62 @@ export const useFloatBox = (slideKeys: ComputedRef) => { const showingBoxKeys = computed(() => Object.keys(floatBoxStates.value).filter((key) => floatBoxStates.value[key].status), ); - const isDragging = ref(false); - const dragstartHandler = () => (isDragging.value = true); - const dragendHandler = (key: string, e: DragEvent) => { - const navMenuRect = services?.uiService?.get('navMenuRect'); - floatBoxStates.value[key] = { - left: e.clientX, - top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0), - status: true, - }; - isDragging.value = false; + const dragState = { + startOffset: { + x: 0, + y: 0, + }, + isDragging: false, }; - document.body.addEventListener('dragover', (e: DragEvent) => { - if (!isDragging.value) return; + const dragstartHandler = (e: DragEvent) => { + dragState.isDragging = true; + + dragState.startOffset.x = e.clientX; + dragState.startOffset.y = e.clientY; + }; + + const effectiveDistance = 20; + + const dragendHandler = (key: string, e: DragEvent) => { + if (!dragState.isDragging) return; + + const { startOffset } = dragState; + + if ( + Math.abs(startOffset.x - e.clientX) > effectiveDistance || + Math.abs(startOffset.y - e.clientY) > effectiveDistance + ) { + const navMenuRect = services?.uiService?.get('navMenuRect'); + floatBoxStates.value[key] = { + left: e.clientX, + top: (navMenuRect?.top ?? 0) + (navMenuRect?.height ?? 0), + status: true, + }; + } + + dragState.isDragging = false; + }; + + const dragoverHandler = (e: DragEvent) => { + if (!dragState.isDragging) return; e.preventDefault(); + }; + + const blurHandler = () => { + dragState.startOffset.x = 0; + dragState.startOffset.y = 0; + + dragState.isDragging = false; + }; + + globalThis.document.body.addEventListener('dragover', dragoverHandler); + globalThis.addEventListener('blur', blurHandler); + + onBeforeUnmount(() => { + globalThis.document.body.removeEventListener('dragover', dragoverHandler); + globalThis.removeEventListener('blur', blurHandler); }); watch(