Skip to content

Commit 06851e6

Browse files
committed
fix(node-resizer): enforce min/max width/height on nodes
1 parent 7cf967a commit 06851e6

File tree

3 files changed

+71
-21
lines changed

3 files changed

+71
-21
lines changed

packages/node-resizer/src/NodeResizer.vue

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
<script lang="ts" setup>
22
// todo: add plugin to emit resize events via vue flow store; requires plugin API to be added to core
3+
import { computed, inject, watch } from 'vue'
4+
import type { NodeDimensionChange } from '@vue-flow/core'
5+
import { NodeIdInjection, useVueFlow } from '@vue-flow/core'
36
import ResizeControl from './ResizeControl.vue'
47
import type { ControlLinePosition, ControlPosition, NodeResizerProps, OnResize, OnResizeStart } from './types'
58
import { ResizeControlVariant } from './types'
69
7-
withDefaults(defineProps<NodeResizerProps>(), {
10+
const props = withDefaults(defineProps<NodeResizerProps>(), {
811
isVisible: true,
912
})
1013
@@ -14,9 +17,58 @@ const emits = defineEmits<{
1417
(event: 'resizeEnd', resizeEvent: OnResizeStart): void
1518
}>()
1619
20+
const { findNode, emits: triggerEmits } = useVueFlow()
21+
1722
const handleControls: ControlPosition[] = ['top-left', 'top-right', 'bottom-left', 'bottom-right']
1823
1924
const lineControls: ControlLinePosition[] = ['top', 'right', 'bottom', 'left']
25+
26+
const contextNodeId = inject(NodeIdInjection, null)
27+
28+
const id = computed(() => (typeof props.nodeId === 'string' ? props.nodeId : contextNodeId))
29+
30+
watch(
31+
[() => props.minWidth, () => props.minHeight, () => props.maxWidth, () => props.maxHeight],
32+
([minWidth, minHeight, maxWidth, maxHeight]) => {
33+
const node = findNode(id.value)
34+
35+
if (node) {
36+
const dimensionChange: NodeDimensionChange = {
37+
id: node.id,
38+
type: 'dimensions',
39+
updateStyle: true,
40+
dimensions: {
41+
width: node.dimensions.width,
42+
height: node.dimensions.height,
43+
},
44+
}
45+
46+
if (minWidth && node.dimensions.width < minWidth) {
47+
dimensionChange.dimensions!.width = minWidth
48+
}
49+
50+
if (minHeight && node.dimensions.height < minHeight) {
51+
dimensionChange.dimensions!.height = minHeight
52+
}
53+
54+
if (maxWidth && node.dimensions.width > maxWidth) {
55+
dimensionChange.dimensions!.width = maxWidth
56+
}
57+
58+
if (maxHeight && node.dimensions.height > maxHeight) {
59+
dimensionChange.dimensions!.height = maxHeight
60+
}
61+
62+
if (
63+
dimensionChange.dimensions!.width !== node.dimensions.width ||
64+
dimensionChange.dimensions!.height !== node.dimensions.height
65+
) {
66+
triggerEmits.nodesChange([dimensionChange])
67+
}
68+
}
69+
},
70+
{ flush: 'post', immediate: true },
71+
)
2072
</script>
2173

2274
<script lang="ts">
@@ -54,7 +106,7 @@ export default {
54106
:key="c"
55107
:class="handleClassName"
56108
:style="handleStyle"
57-
:node-id="nodeId"
109+
:node-id="id"
58110
:position="c"
59111
:color="color"
60112
:min-width="minWidth"

packages/node-resizer/src/ResizeControl.vue

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<script lang="ts" setup>
22
import type { NodeChange, NodeDimensionChange, NodePositionChange } from '@vue-flow/core'
3-
import { NodeIdInjection, clamp, useGetPointerPosition, useVueFlow } from '@vue-flow/core'
3+
import { clamp, useGetPointerPosition, useVueFlow } from '@vue-flow/core'
44
import { select } from 'd3-selection'
55
import { drag } from 'd3-drag'
6-
import { computed, inject, ref, watchEffect } from 'vue'
6+
import { computed, ref, watchEffect } from 'vue'
77
import type { OnResize, OnResizeStart, ResizeControlProps, ResizeDragEvent } from './types'
88
import { ResizeControlVariant } from './types'
99
import { getDirection } from './utils'
@@ -36,22 +36,18 @@ const { findNode, emits: triggerEmits } = useVueFlow()
3636
3737
const getPointerPosition = useGetPointerPosition()
3838
39-
const contextNodeId = inject(NodeIdInjection, null)
40-
4139
const resizeControlRef = ref<HTMLDivElement>()
4240
4341
let startValues: typeof initStartValues = initStartValues
4442
4543
let prevValues: typeof initPrevValues = initPrevValues
4644
47-
const id = computed(() => (typeof props.nodeId === 'string' ? props.nodeId : contextNodeId))
48-
4945
const defaultPosition = computed(() => (props.variant === ResizeControlVariant.Line ? 'right' : 'bottom-right'))
5046
5147
const controlPosition = computed(() => props.position ?? defaultPosition.value)
5248
5349
watchEffect((onCleanup) => {
54-
if (!resizeControlRef.value || !id.value) {
50+
if (!resizeControlRef.value || !props.nodeId) {
5551
return
5652
}
5753
@@ -64,7 +60,7 @@ watchEffect((onCleanup) => {
6460
6561
const dragHandler = drag<HTMLDivElement, unknown>()
6662
.on('start', (event: ResizeDragEvent) => {
67-
const node = findNode(id.value!)
63+
const node = findNode(props.nodeId)
6864
const { xSnapped, ySnapped } = getPointerPosition(event)
6965
7066
prevValues = {
@@ -85,7 +81,7 @@ watchEffect((onCleanup) => {
8581
})
8682
.on('drag', (event: ResizeDragEvent) => {
8783
const { xSnapped, ySnapped } = getPointerPosition(event)
88-
const node = findNode(id.value!)
84+
const node = findNode(props.nodeId)
8985
9086
if (node) {
9187
const changes: NodeChange[] = []
@@ -168,9 +164,9 @@ watchEffect((onCleanup) => {
168164
}
169165
}
170166
171-
if (isWidthChange || isHeightChange) {
167+
if (props.nodeId && (isWidthChange || isHeightChange)) {
172168
const dimensionChange: NodeDimensionChange = {
173-
id: id.value!,
169+
id: props.nodeId,
174170
type: 'dimensions',
175171
updateStyle: true,
176172
resizing: true,
@@ -213,15 +209,17 @@ watchEffect((onCleanup) => {
213209
}
214210
})
215211
.on('end', (event: ResizeDragEvent) => {
216-
const dimensionChange: NodeDimensionChange = {
217-
id: id.value!,
218-
type: 'dimensions',
219-
resizing: false,
220-
}
212+
if (props.nodeId) {
213+
const dimensionChange: NodeDimensionChange = {
214+
id: props.nodeId,
215+
type: 'dimensions',
216+
resizing: false,
217+
}
221218
222-
emits('resizeEnd', { event, params: prevValues })
219+
emits('resizeEnd', { event, params: prevValues })
223220
224-
triggerEmits.nodesChange([dimensionChange])
221+
triggerEmits.nodesChange([dimensionChange])
222+
}
225223
})
226224
227225
selection.call(dragHandler)

packages/node-resizer/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export enum ResizeControlVariant {
6363
}
6464

6565
export interface ResizeControlProps {
66-
nodeId?: string
66+
nodeId?: string | null
6767
color?: string
6868
minWidth?: number
6969
minHeight?: number

0 commit comments

Comments
 (0)