diff --git a/packages/vue-flow/src/composables/useDrag.ts b/packages/vue-flow/src/composables/useDrag.ts index 750e3824..caa6ecda 100644 --- a/packages/vue-flow/src/composables/useDrag.ts +++ b/packages/vue-flow/src/composables/useDrag.ts @@ -22,130 +22,138 @@ interface UseDragParams { } function useDrag(params: UseDragParams) { - const { - viewport, - snapToGrid, - snapGrid, - nodes, - nodeExtent, - getNode, - multiSelectionActive, - selectNodesOnDrag, - removeSelectedElements, - addSelectedNodes, - setState, - updateNodePositions, - } = $(useVueFlow()) - const { onStart, onDrag, onStop, el, disabled = false, noDragClassName, id, handleSelector } = $(params) - - const dragging = ref(false) - let dragItems = $ref() - let lastPos = $ref>({ x: undefined, y: undefined }) - let dragHandler = $ref() - - const getMousePosition = (event: UseDragEvent) => { - const x = event.sourceEvent.touches ? event.sourceEvent.touches[0].clientX : event.sourceEvent.clientX - const y = event.sourceEvent.touches ? event.sourceEvent.touches[0].clientY : event.sourceEvent.clientY - - return pointToRendererPoint( - { - x, - y, - }, + const scope = effectScope() + const dragging = scope.run(() => { + const { viewport, snapToGrid, snapGrid, - ) - } + nodes, + nodeExtent, + getNode, + multiSelectionActive, + selectNodesOnDrag, + removeSelectedElements, + addSelectedNodes, + setState, + updateNodePositions, + } = $(useVueFlow()) - watch( - [() => disabled, () => noDragClassName, () => id, () => el], - () => { - if (el) { - const selection = select(el) - const node = id ? getNode(id) : undefined + const { onStart, onDrag, onStop, el, disabled = false, noDragClassName, id, handleSelector } = $(params) - if (disabled) { - selection.on('.drag', null) - } else { - dragHandler = drag() - .on('start', (event: UseDragEvent) => { - if (!selectNodesOnDrag && !multiSelectionActive && id) { - if (!node?.selected) { - removeSelectedElements() + const dragging = ref(false) + let dragItems = $ref() + let lastPos = $ref>({ x: undefined, y: undefined }) + let dragHandler = $ref() + + const getMousePosition = (event: UseDragEvent) => { + const x = event.sourceEvent.touches ? event.sourceEvent.touches[0].clientX : event.sourceEvent.clientX + const y = event.sourceEvent.touches ? event.sourceEvent.touches[0].clientY : event.sourceEvent.clientY + + return pointToRendererPoint( + { + x, + y, + }, + viewport, + snapToGrid, + snapGrid, + ) + } + + watch( + [() => disabled, () => noDragClassName, () => id, () => el], + () => { + if (el) { + const selection = select(el) + const node = id ? getNode(id) : undefined + + if (disabled) { + selection.on('.drag', null) + } else { + dragHandler = drag() + .on('start', (event: UseDragEvent) => { + if (!selectNodesOnDrag && !multiSelectionActive && id) { + if (!node?.selected) { + removeSelectedElements() + } } - } - if (node && !disabled && selectNodesOnDrag) { - handleNodeClick(node, multiSelectionActive, addSelectedNodes, removeSelectedElements, setState) - } + if (node && !disabled && selectNodesOnDrag) { + handleNodeClick(node, multiSelectionActive, addSelectedNodes, removeSelectedElements, setState) + } - const mousePos = getMousePosition(event) - dragItems = getDragItems(nodes, mousePos, getNode, id) + const mousePos = getMousePosition(event) + dragItems = getDragItems(nodes, mousePos, getNode, id) - if (onStart && dragItems) { - const [currentNode, nodes] = getEventHandlerParams({ - id, - dragItems, - getNode: $$(getNode), - }) - onStart(event.sourceEvent, currentNode, nodes) - } - }) - .on('drag', (event: UseDragEvent) => { - const mousePos = getMousePosition(event) - - // skip events without movement - if ((lastPos.x !== mousePos.x || lastPos.y !== mousePos.y) && dragItems) { - lastPos = mousePos - dragItems = dragItems.map((n) => - updatePosition(n, mousePos, n.parentNode ? getNode(n.parentNode) : undefined, nodeExtent), - ) - - updateNodePositions(dragItems, true, true) - dragging.value = true - - if (onDrag) { + if (onStart && dragItems) { const [currentNode, nodes] = getEventHandlerParams({ id, dragItems, getNode: $$(getNode), }) - onDrag(event.sourceEvent, currentNode, nodes) - } - } - - event.on('end', (event) => { - dragging.value = false - if (onStop && dragItems) { - updateNodePositions(dragItems, false, false) - - const [currentNode, nodes] = getEventHandlerParams({ - id, - dragItems, - getNode: $$(getNode), - }) - onStop(event.sourceEvent, currentNode, nodes) + onStart(event.sourceEvent, currentNode, nodes) } }) - }) - .filter((event: D3DragEvent['sourceEvent']) => { - const target = event.target as HTMLDivElement - return ( - !event.ctrlKey && - !event.button && - (!noDragClassName || - (!hasSelector(target, `.${noDragClassName}`, $$(el)) && - (!handleSelector || hasSelector(target, handleSelector, $$(el))))) - ) - }) + .on('drag', (event: UseDragEvent) => { + const mousePos = getMousePosition(event) - selection.call(dragHandler) + // skip events without movement + if ((lastPos.x !== mousePos.x || lastPos.y !== mousePos.y) && dragItems) { + lastPos = mousePos + dragItems = dragItems.map((n) => + updatePosition(n, mousePos, n.parentNode ? getNode(n.parentNode) : undefined, nodeExtent), + ) + + updateNodePositions(dragItems, true, true) + dragging.value = true + + if (onDrag) { + const [currentNode, nodes] = getEventHandlerParams({ + id, + dragItems, + getNode: $$(getNode), + }) + onDrag(event.sourceEvent, currentNode, nodes) + } + } + + event.on('end', (event) => { + dragging.value = false + if (onStop && dragItems) { + updateNodePositions(dragItems, false, false) + + const [currentNode, nodes] = getEventHandlerParams({ + id, + dragItems, + getNode: $$(getNode), + }) + onStop(event.sourceEvent, currentNode, nodes) + } + }) + }) + .filter((event: D3DragEvent['sourceEvent']) => { + const target = event.target as HTMLDivElement + return ( + !event.ctrlKey && + !event.button && + (!noDragClassName || + (!hasSelector(target, `.${noDragClassName}`, $$(el)) && + (!handleSelector || hasSelector(target, handleSelector, $$(el))))) + ) + }) + + selection.call(dragHandler) + } } - } - }, - { flush: 'post' }, - ) + }, + { flush: 'post' }, + ) + + return dragging + }) + + tryOnScopeDispose(() => scope.stop()) return dragging }