feat(nodes): add effect scope to useDrag utility

This commit is contained in:
bcakmakoglu
2022-06-07 18:33:00 +02:00
committed by Braks
parent f434ab0f79
commit 382a3b67fc
+114 -106
View File
@@ -22,130 +22,138 @@ interface UseDragParams {
} }
function useDrag(params: UseDragParams) { function useDrag(params: UseDragParams) {
const { const scope = effectScope()
viewport, const dragging = scope.run(() => {
snapToGrid, const {
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<NodeDragItem[]>()
let lastPos = $ref<Partial<XYPosition>>({ x: undefined, y: undefined })
let dragHandler = $ref<any>()
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, viewport,
snapToGrid, snapToGrid,
snapGrid, snapGrid,
) nodes,
} nodeExtent,
getNode,
multiSelectionActive,
selectNodesOnDrag,
removeSelectedElements,
addSelectedNodes,
setState,
updateNodePositions,
} = $(useVueFlow())
watch( const { onStart, onDrag, onStop, el, disabled = false, noDragClassName, id, handleSelector } = $(params)
[() => disabled, () => noDragClassName, () => id, () => el],
() => {
if (el) {
const selection = select(el)
const node = id ? getNode(id) : undefined
if (disabled) { const dragging = ref(false)
selection.on('.drag', null) let dragItems = $ref<NodeDragItem[]>()
} else { let lastPos = $ref<Partial<XYPosition>>({ x: undefined, y: undefined })
dragHandler = drag() let dragHandler = $ref<any>()
.on('start', (event: UseDragEvent) => {
if (!selectNodesOnDrag && !multiSelectionActive && id) { const getMousePosition = (event: UseDragEvent) => {
if (!node?.selected) { const x = event.sourceEvent.touches ? event.sourceEvent.touches[0].clientX : event.sourceEvent.clientX
removeSelectedElements() 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) { if (node && !disabled && selectNodesOnDrag) {
handleNodeClick(node, multiSelectionActive, addSelectedNodes, removeSelectedElements, setState) handleNodeClick(node, multiSelectionActive, addSelectedNodes, removeSelectedElements, setState)
} }
const mousePos = getMousePosition(event) const mousePos = getMousePosition(event)
dragItems = getDragItems(nodes, mousePos, getNode, id) dragItems = getDragItems(nodes, mousePos, getNode, id)
if (onStart && dragItems) { 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) {
const [currentNode, nodes] = getEventHandlerParams({ const [currentNode, nodes] = getEventHandlerParams({
id, id,
dragItems, dragItems,
getNode: $$(getNode), getNode: $$(getNode),
}) })
onDrag(event.sourceEvent, currentNode, nodes) onStart(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)
} }
}) })
}) .on('drag', (event: UseDragEvent) => {
.filter((event: D3DragEvent<HTMLDivElement, null, SubjectPosition>['sourceEvent']) => { const mousePos = getMousePosition(event)
const target = event.target as HTMLDivElement
return (
!event.ctrlKey &&
!event.button &&
(!noDragClassName ||
(!hasSelector(target, `.${noDragClassName}`, $$(el)) &&
(!handleSelector || hasSelector(target, handleSelector, $$(el)))))
)
})
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<HTMLDivElement, null, SubjectPosition>['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 return dragging
} }