feat(node-resizer): add shouldResize option

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
braks
2023-02-02 14:28:22 +01:00
committed by Braks
parent f0043258d0
commit 222b58afd4
5 changed files with 92 additions and 20 deletions

View File

@@ -1,20 +1,21 @@
<script lang="ts" setup>
// todo: add plugin to emit resize events via vue flow store; requires plugin API to be added to core
import ResizeControl from './ResizeControl.vue'
import type { ControlLinePosition, ControlPosition, NodeResizerProps, ResizeDragEvent, ResizeEventParams } from './types'
import type { ControlLinePosition, ControlPosition, NodeResizerProps, OnResize, OnResizeStart } from './types'
import { ResizeControlVariant } from './types'
const props = withDefaults(defineProps<NodeResizerProps>(), {
withDefaults(defineProps<NodeResizerProps>(), {
isVisible: true,
})
const emits = defineEmits<{
(event: 'resizeStart', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resize', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeEnd', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeStart', resizeEvent: OnResizeStart): void
(event: 'resize', resizeEvent: OnResize): void
(event: 'resizeEnd', resizeEvent: OnResizeStart): void
}>()
const handleControls: ControlPosition[] = ['top-left', 'top-right', 'bottom-left', 'bottom-right']
const lineControls: ControlLinePosition[] = ['top', 'right', 'bottom', 'left']
</script>
@@ -37,10 +38,12 @@ export default {
:color="color"
:min-width="minWidth"
:min-height="minHeight"
:should-resize="shouldResize"
@resize-start="emits('resizeStart', $event)"
@resize="emits('resize', $event)"
@resize-end="emits('resizeEnd', $event)"
/>
<ResizeControl
v-for="c of handleControls"
:key="c"
@@ -51,6 +54,7 @@ export default {
:color="color"
:min-width="minWidth"
:min-height="minHeight"
:should-resize="shouldResize"
@resize-start="emits('resizeStart', $event)"
@resize="emits('resize', $event)"
@resize-end="emits('resizeEnd', $event)"

View File

@@ -3,8 +3,9 @@ import type { NodeChange, NodeDimensionChange, NodePositionChange } from '@vue-f
import { NodeIdInjection, useGetPointerPosition, useVueFlow } from '@vue-flow/core'
import { select } from 'd3-selection'
import { drag } from 'd3-drag'
import type { ResizeControlProps, ResizeDragEvent, ResizeEventParams } from './types'
import type { OnResize, OnResizeStart, ResizeControlProps, ResizeDragEvent } from './types'
import { ResizeControlVariant } from './types'
import { getDirection } from './utils'
const props = withDefaults(defineProps<ResizeControlProps>(), {
variant: 'handle' as ResizeControlVariant,
@@ -13,9 +14,9 @@ const props = withDefaults(defineProps<ResizeControlProps>(), {
})
const emits = defineEmits<{
(event: 'resizeStart', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resize', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeEnd', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeStart', resizeEvent: OnResizeStart): void
(event: 'resize', resizeEvent: OnResize): void
(event: 'resizeEnd', resizeEvent: OnResizeStart): void
}>()
const initPrevValues = { width: 0, height: 0, x: 0, y: 0 }
@@ -142,7 +143,24 @@ watchEffect((onCleanup) => {
prevValues.value.height = height
}
emits('resize', { event, params: prevValues.value })
if (changes.length === 0) return
const direction = getDirection({
width: prevValues.value.width,
prevWidth,
height: prevValues.value.height,
prevHeight,
invertX,
invertY,
})
const nextValues = { ...prevValues.value, direction }
const callResize = props.shouldResize?.(event, nextValues)
if (callResize === false) return
emits('resize', { event, params: nextValues })
triggerEmits.nodesChange(changes)
}

View File

@@ -1,14 +1,14 @@
<script lang="ts" setup>
import ResizeControl from './ResizeControl.vue'
import type { ResizeControlLineProps, ResizeDragEvent, ResizeEventParams } from './types'
import type { OnResize, OnResizeStart, ResizeControlLineProps } from './types'
import { ResizeControlVariant } from './types'
const props = defineProps<ResizeControlLineProps>()
const emits = defineEmits<{
(event: 'resizeStart', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resize', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeEnd', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeStart', resizeEvent: OnResizeStart): void
(event: 'resize', resizeEvent: OnResize): void
(event: 'resizeEnd', resizeEvent: OnResizeStart): void
}>()
</script>

View File

@@ -1,13 +1,36 @@
import type { D3DragEvent, SubjectPosition } from 'd3-drag'
import type { CSSProperties } from 'vue'
export interface ResizeEventParams {
export type ResizeDragEvent = D3DragEvent<HTMLDivElement, null, SubjectPosition>
export type ResizeParamsWithDirection = ResizeParams & {
direction: number[]
}
export interface ResizeParams {
x: number
y: number
width: number
height: number
}
export type ShouldResize = (event: ResizeDragEvent, params: ResizeParamsWithDirection) => boolean
export interface OnResizeStart {
event: ResizeDragEvent
params: ResizeParams
}
export interface OnResize {
event: ResizeDragEvent
params: ResizeParamsWithDirection
}
export interface OnResizeEnd {
event: ResizeDragEvent
params: ResizeParams
}
export interface NodeResizerProps {
nodeId?: string
color?: string
@@ -18,12 +41,13 @@ export interface NodeResizerProps {
isVisible?: boolean
minWidth?: number
minHeight?: number
shouldResize?: ShouldResize
}
export interface NodeResizerEmits {
(event: 'resizeStart', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resize', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeEnd', data: { event: ResizeDragEvent; params: ResizeEventParams }): void
(event: 'resizeStart', resizeEvent: OnResizeStart): void
(event: 'resize', resizeEvent: OnResize): void
(event: 'resizeEnd', resizeEvent: OnResizeStart): void
}
export type ControlLinePosition = 'top' | 'bottom' | 'left' | 'right'
@@ -42,6 +66,7 @@ export interface ResizeControlProps {
minHeight?: number
position?: ControlPosition
variant?: ResizeControlVariant
shouldResize?: ShouldResize
}
export interface ResizeControlLineProps {
@@ -52,5 +77,3 @@ export interface ResizeControlLineProps {
variant?: ResizeControlVariant
position?: ControlLinePosition
}
export type ResizeDragEvent = D3DragEvent<HTMLDivElement, null, SubjectPosition>

View File

@@ -0,0 +1,27 @@
interface GetDirectionParams {
width: number
prevWidth: number
height: number
prevHeight: number
invertX: boolean
invertY: boolean
}
// returns an array of two numbers (0, 1 or -1) representing the direction of the resize
// 0 = no change, 1 = increase, -1 = decrease
export function getDirection({ width, prevWidth, height, prevHeight, invertX, invertY }: GetDirectionParams) {
const deltaWidth = width - prevWidth
const deltaHeight = height - prevHeight
const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0]
if (deltaWidth && invertX) {
direction[0] = direction[0] * -1
}
if (deltaHeight && invertY) {
direction[1] = direction[1] * -1
}
return direction
}