Files
vue-flow/packages/resize-rotate-node/src/node/ResizeRotateNode.vue
T

118 lines
2.9 KiB
Vue

<script lang="ts" setup>
import Moveable from 'vue3-moveable'
import type { Dimensions } from '@vue-flow/core'
import { Handle, useVueFlow } from '@vue-flow/core'
import { useMoveable } from './utils'
import type { ResizeRotateNodeProps } from './types'
interface Emits {
(event: 'updateNodeInternals'): void
(event: 'resize', dimensions: Dimensions): void
(event: 'rotate', rotation: number): void
}
const props = withDefaults(defineProps<ResizeRotateNodeProps>(), {
resizable: true,
rotatable: true,
moveableProps: () => ({}),
})
const emits = defineEmits<Emits>()
const { findNode, onPaneClick, onNodeClick, onNodeDragStart, snapGrid, snapToGrid } = useVueFlow()
const el = ref()
const visible = ref(false)
const { onRotateStart, onRotate, onResizeStart, onResize, onResizeEnd } = useMoveable(props.id, emits)
const toggleVisibility = (val?: boolean) => {
visible.value = val ?? !visible.value
}
onNodeClick(({ node }) => {
toggleVisibility(node.id === props.id)
})
onNodeDragStart(({ node }) => {
toggleVisibility(node.id === props.id)
})
onPaneClick(() => toggleVisibility(false))
onBeforeMount(() => {
const node = findNode(props.id)!
node.dragHandle = `[data-moveable-id='${props.id}']`
const previousStyle = node.style
node.style = () => {
return {
...previousStyle,
pointerEvents: 'none',
cursor: 'default',
}
}
})
</script>
<script lang="ts">
export default {
inheritAttrs: false,
}
</script>
<template>
<div
ref="el"
style="cursor: grab; pointer-events: all"
:data-moveable-id="props.id"
:style="{
...data.style,
cursor: visible ? 'grab' : 'auto',
zIndex: visible ? 1000 : 0,
width: data.dimensions?.width ? `${data.dimensions.width}px` : undefined,
height: data.dimensions?.height ? `${data.dimensions.height}px` : undefined,
transform: `translate(${data.translate[0]}px, ${data.translate[1]}px)` + ` rotate(${data.rotate}deg)`,
}"
>
<Handle type="target" :position="props.targetPosition" />
<slot>
{{ props.label }}
</slot>
<Handle type="source" :position="props.sourcePosition" />
</div>
<Moveable
v-bind="props.moveableProps"
class-name="nodrag"
style="pointer-events: all"
:target="visible ? el : undefined"
:resizable="resizable"
:rotatable="rotatable"
:snappable="snapToGrid"
:snap-element="snapToGrid"
:snap-gap="snapToGrid"
:snap-directions="snapToGrid"
:snap-digit="snapGrid[0]"
:snap-treshold="snapGrid[0]"
:snap-grid-width="snapGrid[0]"
:snap-grid-height="snapGrid[1]"
:padding="{ left: 0, top: 0, right: 0, bottom: 0 }"
:origin="false"
:start-drag-rotate="0"
:throttle-drag-rotate="0"
:throttle-resize="1"
:render-directions="['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se']"
:zoom="1"
@resize-start="onResizeStart"
@resize="onResize"
@resize-end="onResizeEnd"
@rotate-start="onRotateStart"
@rotate="onRotate"
/>
</template>