refactor(node-resizer): add auto-scale prop & scale resize controls with zoom level (#1872)
* refactor(node-resizer): add auto-scale prop & scale resize controls with zoom Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> * chore(changeset): add --------- Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@vue-flow/node-resizer": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add auto-scale prop to node resizer (default `true`) that forces node resizer controls to scale with the viewport zoom level.
|
||||||
@@ -8,6 +8,7 @@ import { ResizeControlVariant } from './types'
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<NodeResizerProps>(), {
|
const props = withDefaults(defineProps<NodeResizerProps>(), {
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
autoScale: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emits = defineEmits<NodeResizerEmits>()
|
const emits = defineEmits<NodeResizerEmits>()
|
||||||
@@ -92,13 +93,14 @@ export default {
|
|||||||
:node-id="nodeId"
|
:node-id="nodeId"
|
||||||
:position="c"
|
:position="c"
|
||||||
:variant="ResizeControlVariant.Line"
|
:variant="ResizeControlVariant.Line"
|
||||||
:keep-aspect-ratio="keepAspectRatio"
|
|
||||||
:color="color"
|
:color="color"
|
||||||
:min-width="minWidth"
|
:min-width="minWidth"
|
||||||
:min-height="minHeight"
|
:min-height="minHeight"
|
||||||
:max-width="maxWidth"
|
:max-width="maxWidth"
|
||||||
:max-height="maxHeight"
|
:max-height="maxHeight"
|
||||||
:should-resize="shouldResize"
|
:should-resize="shouldResize"
|
||||||
|
:keep-aspect-ratio="keepAspectRatio"
|
||||||
|
:auto-scale="autoScale"
|
||||||
@resize-start="emits('resizeStart', $event)"
|
@resize-start="emits('resizeStart', $event)"
|
||||||
@resize="emits('resize', $event)"
|
@resize="emits('resize', $event)"
|
||||||
@resize-end="emits('resizeEnd', $event)"
|
@resize-end="emits('resizeEnd', $event)"
|
||||||
@@ -118,6 +120,7 @@ export default {
|
|||||||
:max-height="maxHeight"
|
:max-height="maxHeight"
|
||||||
:should-resize="shouldResize"
|
:should-resize="shouldResize"
|
||||||
:keep-aspect-ratio="keepAspectRatio"
|
:keep-aspect-ratio="keepAspectRatio"
|
||||||
|
:auto-scale="autoScale"
|
||||||
@resize-start="emits('resizeStart', $event)"
|
@resize-start="emits('resizeStart', $event)"
|
||||||
@resize="emits('resize', $event)"
|
@resize="emits('resize', $event)"
|
||||||
@resize-end="emits('resizeEnd', $event)"
|
@resize-end="emits('resizeEnd', $event)"
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import type { NodeChange, NodeDimensionChange, NodePositionChange } from '@vue-f
|
|||||||
import { clamp, useGetPointerPosition, useVueFlow } from '@vue-flow/core'
|
import { clamp, useGetPointerPosition, useVueFlow } from '@vue-flow/core'
|
||||||
import { select } from 'd3-selection'
|
import { select } from 'd3-selection'
|
||||||
import { drag } from 'd3-drag'
|
import { drag } from 'd3-drag'
|
||||||
import { ref, toRef, watchEffect } from 'vue'
|
import { computed, ref, toRef, watchEffect } from 'vue'
|
||||||
import type { NodeResizerEmits, ResizeControlProps, ResizeControlVariant, ResizeDragEvent } from './types'
|
import type { NodeResizerEmits, ResizeControlProps, ResizeDragEvent } from './types'
|
||||||
|
import { ResizeControlVariant } from './types'
|
||||||
import { DefaultPositions, StylingProperty, getDirection } from './utils'
|
import { DefaultPositions, StylingProperty, getDirection } from './utils'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<ResizeControlProps>(), {
|
const props = withDefaults(defineProps<ResizeControlProps>(), {
|
||||||
@@ -14,6 +15,7 @@ const props = withDefaults(defineProps<ResizeControlProps>(), {
|
|||||||
maxWidth: Number.MAX_VALUE,
|
maxWidth: Number.MAX_VALUE,
|
||||||
maxHeight: Number.MAX_VALUE,
|
maxHeight: Number.MAX_VALUE,
|
||||||
keepAspectRatio: false,
|
keepAspectRatio: false,
|
||||||
|
autoScale: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emits = defineEmits<NodeResizerEmits>()
|
const emits = defineEmits<NodeResizerEmits>()
|
||||||
@@ -27,7 +29,7 @@ const initStartValues = {
|
|||||||
aspectRatio: 1,
|
aspectRatio: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { findNode, emits: triggerEmits } = useVueFlow()
|
const { findNode, emits: triggerEmits, viewport, noDragClassName } = useVueFlow()
|
||||||
|
|
||||||
const getPointerPosition = useGetPointerPosition()
|
const getPointerPosition = useGetPointerPosition()
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ let prevValues: typeof initPrevValues = initPrevValues
|
|||||||
|
|
||||||
const controlPosition = toRef(() => props.position ?? DefaultPositions[props.variant])
|
const controlPosition = toRef(() => props.position ?? DefaultPositions[props.variant])
|
||||||
|
|
||||||
const positionClassNames = toRef(() => controlPosition.value.split('-'))
|
const positionClassNames = computed(() => controlPosition.value.split('-'))
|
||||||
|
|
||||||
const controlStyle = toRef(() => (props.color ? { [StylingProperty[props.variant]]: props.color } : {}))
|
const controlStyle = toRef(() => (props.color ? { [StylingProperty[props.variant]]: props.color } : {}))
|
||||||
|
|
||||||
@@ -237,9 +239,12 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="resizeControlRef"
|
ref="resizeControlRef"
|
||||||
class="vue-flow__resize-control nodrag"
|
class="vue-flow__resize-control"
|
||||||
:class="[...positionClassNames, variant]"
|
:class="[...positionClassNames, variant, noDragClassName]"
|
||||||
:style="controlStyle"
|
:style="{
|
||||||
|
...controlStyle,
|
||||||
|
scale: variant === ResizeControlVariant.Handle ? `${Math.max(1 / viewport.zoom, 1)}` : undefined,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
/* handle styles */
|
/* handle styles */
|
||||||
.vue-flow__resize-control.handle {
|
.vue-flow__resize-control.handle {
|
||||||
width: 4px;
|
width: 5px;
|
||||||
height: 4px;
|
height: 5px;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
background-color: #3367d9;
|
background-color: #3367d9;
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ export interface NodeResizerProps {
|
|||||||
maxHeight?: number
|
maxHeight?: number
|
||||||
shouldResize?: ShouldResize
|
shouldResize?: ShouldResize
|
||||||
keepAspectRatio?: boolean | number
|
keepAspectRatio?: boolean | number
|
||||||
|
/**
|
||||||
|
* Scale the controls with the zoom level.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
autoScale?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeResizerEmits {
|
export interface NodeResizerEmits {
|
||||||
@@ -62,8 +67,8 @@ export enum ResizeControlVariant {
|
|||||||
Handle = 'handle',
|
Handle = 'handle',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResizeControlProps {
|
export interface ResizeControlProps extends NodeResizerProps {
|
||||||
nodeId?: string | null
|
nodeId?: string
|
||||||
color?: string
|
color?: string
|
||||||
minWidth?: number
|
minWidth?: number
|
||||||
minHeight?: number
|
minHeight?: number
|
||||||
@@ -73,6 +78,11 @@ export interface ResizeControlProps {
|
|||||||
variant?: ResizeControlVariant
|
variant?: ResizeControlVariant
|
||||||
shouldResize?: ShouldResize
|
shouldResize?: ShouldResize
|
||||||
keepAspectRatio?: boolean | number
|
keepAspectRatio?: boolean | number
|
||||||
|
/**
|
||||||
|
* Scale the controls with the zoom level.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
autoScale?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResizeControlLineProps extends ResizeControlProps {
|
export interface ResizeControlLineProps extends ResizeControlProps {
|
||||||
|
|||||||
Reference in New Issue
Block a user