import { useEventListener } from "@vueuse/core"; import { type Ref, watch } from "vue"; import { useWorkflowStores } from "@/composables/workflowStores"; import { vecSnap } from "../modules/geometry"; /** * Common functionality required for handling a user resizable element. * `resize: both` needs to be set on the elements style, this composable * will not apply it. * * @param target Element to attach to * @param sizeControl External override for the size. Will override the user resize when set * @param onResized Function to run when the target element receives a mouseup event, and it's size changed */ export function useResizable( target: Ref, sizeControl: Ref<[number, number]>, onResized: (size: [number, number]) => void, ) { // override user resize if size changes externally watch( () => sizeControl.value, ([width, height]) => { const element = target.value; if (element) { element.style.width = `${width}px`; element.style.height = `${height}px`; } }, ); let prevWidth = sizeControl.value[0]; let prevHeight = sizeControl.value[1]; const { toolbarStore } = useWorkflowStores(); useEventListener(target, "mouseup", () => { const element = target.value; if (element) { const width = element.offsetWidth; const height = element.offsetHeight; if (prevWidth !== width || prevHeight !== height) { if (toolbarStore.snapActive) { onResized(vecSnap([width, height], toolbarStore.snapDistance)); } else { onResized([width, height]); } prevWidth = width; prevHeight = height; } } }); }