refactor(nodes): Remove DraggableCore component and use composable

* Remove node-element prop from NodeProps
This commit is contained in:
Braks
2022-04-11 11:30:10 +02:00
parent 676c984e07
commit 4f026e841a
2 changed files with 101 additions and 98 deletions
+100 -95
View File
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { DraggableEventListener, DraggableCore } from '@braks/revue-draggable'
import { useDraggableCore } from '@braks/revue-draggable'
import { useVueFlow } from '../../composables'
import { GraphNode, NodeComponent, SnapGrid } from '../../types'
import { NodeId, Slots } from '../../context'
@@ -42,38 +42,6 @@ const onSelectNodeHandler = (event: MouseEvent) => {
store.hooks.nodeClick.trigger({ event, node: node.value })
}
}
const onDragStart: DraggableEventListener = ({ event }) => {
store.addSelectedNodes([])
store.hooks.nodeDragStart.trigger({ event, node: node.value })
if (store.selectNodesOnDrag && props.selectable) {
store.nodesSelectionActive = false
if (!node.value.selected) store.addSelectedNodes([node.value])
} else if (!store.selectNodesOnDrag && !node.value.selected && props.selectable) {
store.nodesSelectionActive = false
store.addSelectedNodes([])
}
}
const onDrag: DraggableEventListener = ({ event, data: { deltaX, deltaY } }) => {
nextTick(() => store.updateNodePosition({ id: node.value.id, diff: { x: deltaX, y: deltaY }, dragging: true }))
store.hooks.nodeDrag.trigger({ event, node: node.value })
}
const onDragStop: DraggableEventListener = ({ event, data: { deltaX, deltaY } }) => {
// onDragStop also gets called when user just clicks on a node.
// Because of that we set dragging to true inside the onDrag handler and handle the click here
if (!node.value.dragging) {
if (props.selectable && !store.selectNodesOnDrag && !node.value.selected) {
store.addSelectedNodes([node.value])
}
store.hooks.nodeClick.trigger({ event, node: node.value })
return
}
store.updateNodePosition({ id: node.value.id, diff: { x: deltaX, y: deltaY }, dragging: false })
store.hooks.nodeDragStop.trigger({ event, node: node.value })
}
const size = ref<Record<string, string>>()
onMounted(() => {
const { width, height } = nodeElement.value.getBoundingClientRect()
@@ -156,6 +124,57 @@ const type = computed(() => {
return slot
})
const { scale, onDrag, onDragStart, onDragStop } = useDraggableCore(nodeElement, {
handle: node.value.dragHandle,
disabled: !props.draggable,
grid: props.snapGrid,
cancel: `.${store.noDragClassName}`,
enableUserSelectHack: false,
})
onMounted(() => {
watchDebounced(
() => store.transform[2],
() => {
scale.value = store.transform[2]
},
{ debounce: 5 },
)
})
onDragStart(({ event }) => {
store.addSelectedNodes([])
store.hooks.nodeDragStart.trigger({ event, node: node.value })
if (store.selectNodesOnDrag && props.selectable) {
store.nodesSelectionActive = false
if (!node.value.selected) store.addSelectedNodes([node.value])
} else if (!store.selectNodesOnDrag && !node.value.selected && props.selectable) {
store.nodesSelectionActive = false
store.addSelectedNodes([])
}
})
onDrag(({ event, data: { deltaX, deltaY } }) => {
nextTick(() => store.updateNodePosition({ id: node.value.id, diff: { x: deltaX, y: deltaY }, dragging: true }))
store.hooks.nodeDrag.trigger({ event, node: node.value })
})
onDragStop(({ event, data: { deltaX, deltaY } }) => {
// onDragStop also gets called when user just clicks on a node.
// Because of that we set dragging to true inside the onDrag handler and handle the click here
if (!node.value.dragging) {
if (props.selectable && !store.selectNodesOnDrag && !node.value.selected) {
store.addSelectedNodes([node.value])
}
store.hooks.nodeClick.trigger({ event, node: node.value })
return
}
store.updateNodePosition({ id: node.value.id, diff: { x: deltaX, y: deltaY }, dragging: false })
store.hooks.nodeDragStop.trigger({ event, node: node.value })
})
</script>
<script lang="ts">
export default {
@@ -164,67 +183,53 @@ export default {
}
</script>
<template>
<DraggableCore
:cancel="`.${store.noDragClassName}`"
:handle="node.dragHandle"
:disabled="!props.draggable"
:scale="scaleDebounced"
:grid="props.snapGrid"
:enable-user-select-hack="false"
@start="onDragStart"
@move="onDrag"
@stop="onDragStop"
<div
ref="node-element"
:key="`node-${node.id}`"
:class="[
'vue-flow__node',
`vue-flow__node-${name}`,
store.noPanClassName,
{
dragging: node.dragging,
selected: node.selected,
selectable: props.selectable,
},
getClass(),
]"
:style="{
zIndex: node.computedPosition.z,
transform: `translate(${node.computedPosition.x}px,${node.computedPosition.y}px)`,
pointerEvents: props.selectable || props.draggable ? 'all' : 'none',
...getStyle(),
}"
:data-id="node.id"
@mouseenter="onMouseEnterHandler"
@mousemove="onMouseMoveHandler"
@mouseleave="onMouseLeaveHandler"
@contextmenu="onContextMenuHandler"
@click="onSelectNodeHandler"
@dblclick="onDoubleClick"
>
<div
ref="node-element"
:key="`node-${node.id}`"
:class="[
'vue-flow__node',
`vue-flow__node-${name}`,
store.noPanClassName,
{
dragging: node.dragging,
selected: node.selected,
selectable: props.selectable,
},
getClass(),
]"
:style="{
zIndex: node.computedPosition.z,
transform: `translate(${node.computedPosition.x}px,${node.computedPosition.y}px)`,
pointerEvents: props.selectable || props.draggable ? 'all' : 'none',
...size,
...getStyle(),
}"
:data-id="node.id"
@mouseenter="onMouseEnterHandler"
@mousemove="onMouseMoveHandler"
@mouseleave="onMouseLeaveHandler"
@contextmenu="onContextMenuHandler"
@click="onSelectNodeHandler"
@dblclick="onDoubleClick"
>
<component
:is="type"
:id="node.id"
:node-element="nodeElement"
:type="node.type"
:data="node.data"
:selected="!!node.selected"
:connectable="props.connectable"
:position="node.position"
:computed-position="node.computedPosition"
:dimensions="node.dimensions"
:is-valid-target-pos="node.isValidTargetPos"
:is-valid-source-pos="node.isValidSourcePos"
:parent-node="node.parentNode"
:dragging="!!node.dragging"
:z-index="node.computedPosition.z"
:target-position="node.targetPosition"
:source-position="node.sourcePosition"
:label="node.label"
:drag-handle="node.dragHandle"
/>
</div>
</DraggableCore>
<component
:is="type"
:id="node.id"
:type="node.type"
:data="node.data"
:selected="!!node.selected"
:connectable="props.connectable"
:position="node.position"
:computed-position="node.computedPosition"
:dimensions="node.dimensions"
:is-valid-target-pos="node.isValidTargetPos"
:is-valid-source-pos="node.isValidSourcePos"
:parent-node="node.parentNode"
:dragging="!!node.dragging"
:z-index="node.computedPosition.z"
:target-position="node.targetPosition"
:source-position="node.sourcePosition"
:label="node.label"
:drag-handle="node.dragHandle"
/>
</div>
</template>
+1 -3
View File
@@ -52,8 +52,6 @@ export interface GraphNode<Data = ElementData> extends Node<Data> {
/** these props are passed to node components */
export interface NodeProps<Data = ElementData> {
id: string
/** node DOM-element */
nodeElement: HTMLDivElement
type: string
data?: Data
selected: boolean
@@ -62,7 +60,7 @@ export interface NodeProps<Data = ElementData> {
computedPosition: XYZPosition
/** x, y position */
position: XYPosition
/** node dimensions (width, height) */
/** dom element dimensions (width, height) */
dimensions: Dimensions
label?:
| string