Merge pull request #5528 from xyflow/resizer-update-keep-aspect
NodeResizer: Make parameters dynamic
This commit is contained in:
7
.changeset/flat-horses-smile.md
Normal file
7
.changeset/flat-horses-smile.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@xyflow/system': patch
|
||||
'@xyflow/react': patch
|
||||
'@xyflow/svelte': patch
|
||||
---
|
||||
|
||||
Let NodeResizer props change during ongoing resize
|
||||
@@ -1,7 +1,9 @@
|
||||
import { memo, FC } from 'react';
|
||||
import { Handle, Position, NodeProps, NodeResizer } from '@xyflow/react';
|
||||
import { Handle, Position, NodeProps, NodeResizer, useKeyPress } from '@xyflow/react';
|
||||
|
||||
const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
|
||||
const keepAspectRatio = useKeyPress('k');
|
||||
|
||||
return (
|
||||
<>
|
||||
<NodeResizer
|
||||
@@ -14,7 +16,7 @@ const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
/>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div>{data.label}</div>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
import '@xyflow/svelte/dist/style.css';
|
||||
import type { ResizeNode } from './types';
|
||||
import { store } from './store.svelte';
|
||||
|
||||
const nodeTypes = {
|
||||
defaultResizer: DefaultResizer,
|
||||
@@ -139,6 +140,15 @@
|
||||
let snapToGrid = $state(false);
|
||||
</script>
|
||||
|
||||
<svelte:window
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'k') store.keepAspectRatio = true;
|
||||
}}
|
||||
on:keyup={(e) => {
|
||||
if (e.key === 'k') store.keepAspectRatio = false;
|
||||
}}
|
||||
/>
|
||||
|
||||
<SvelteFlow
|
||||
bind:nodes
|
||||
bind:edges
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Handle, Position, type NodeProps, NodeResizeControl, type Node } from '@xyflow/svelte';
|
||||
import type { ResizeNode } from './types';
|
||||
import { store } from './store.svelte';
|
||||
|
||||
let { data }: NodeProps<ResizeNode> = $props();
|
||||
</script>
|
||||
@@ -14,7 +15,7 @@
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={store.keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
style="background: transparent; border: none;"
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { Handle, NodeResizer, Position, type NodeProps } from '@xyflow/svelte';
|
||||
import type { ResizeNode } from './types';
|
||||
|
||||
import { store } from './store.svelte';
|
||||
|
||||
let { data, selected }: NodeProps<ResizeNode> = $props();
|
||||
</script>
|
||||
|
||||
@@ -15,7 +17,7 @@
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={store.keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
/>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div>{data.label}</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
|
||||
import type { ResizeNode } from './types';
|
||||
import { store } from './store.svelte';
|
||||
|
||||
let { data }: NodeProps<ResizeNode> = $props();
|
||||
</script>
|
||||
@@ -14,7 +15,7 @@
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={store.keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
color="red"
|
||||
position={Position.Left}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
|
||||
import type { ResizeNode } from './types';
|
||||
import { store } from './store.svelte';
|
||||
|
||||
let { data }: NodeProps<ResizeNode> = $props();
|
||||
</script>
|
||||
@@ -14,7 +15,7 @@
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
keepAspectRatio={store.keepAspectRatio || (data.keepAspectRatio ?? undefined)}
|
||||
color="red"
|
||||
position={Position.Top}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
function createStore() {
|
||||
let keepAspectRatio = $state(false);
|
||||
|
||||
return {
|
||||
get keepAspectRatio() {
|
||||
return keepAspectRatio;
|
||||
},
|
||||
set keepAspectRatio(value: boolean) {
|
||||
keepAspectRatio = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const store = createStore();
|
||||
@@ -104,6 +104,18 @@ function nodeToChildExtent(child: NodeBase, parent: NodeBase, nodeOrigin: NodeOr
|
||||
export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: XYResizerParams): XYResizerInstance {
|
||||
const selection = select(domNode);
|
||||
|
||||
let params = {
|
||||
controlDirection: getControlDirection('bottom-right'),
|
||||
boundaries: {
|
||||
minWidth: 0,
|
||||
minHeight: 0,
|
||||
maxWidth: Number.MAX_VALUE,
|
||||
maxHeight: Number.MAX_VALUE,
|
||||
},
|
||||
resizeDirection: undefined as ResizeControlDirection | undefined,
|
||||
keepAspectRatio: false,
|
||||
};
|
||||
|
||||
function update({
|
||||
controlPosition,
|
||||
boundaries,
|
||||
@@ -117,7 +129,12 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
|
||||
let prevValues = { ...initPrevValues };
|
||||
let startValues = { ...initStartValues };
|
||||
|
||||
const controlDirection = getControlDirection(controlPosition);
|
||||
params = {
|
||||
boundaries,
|
||||
resizeDirection,
|
||||
keepAspectRatio,
|
||||
controlDirection: getControlDirection(controlPosition),
|
||||
};
|
||||
|
||||
let node: InternalNodeBase | undefined = undefined;
|
||||
let containerBounds: DOMRect | null = null;
|
||||
@@ -212,16 +229,17 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
|
||||
const change: XYResizerChange = {};
|
||||
const nodeOrigin = node.origin ?? storeNodeOrigin;
|
||||
|
||||
const { width, height, x, y } = getDimensionsAfterResize(
|
||||
startValues,
|
||||
controlDirection,
|
||||
params.controlDirection,
|
||||
pointerPosition,
|
||||
boundaries,
|
||||
keepAspectRatio,
|
||||
params.boundaries,
|
||||
params.keepAspectRatio,
|
||||
nodeOrigin,
|
||||
parentExtent,
|
||||
childExtent
|
||||
@@ -264,9 +282,13 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
|
||||
|
||||
if (isWidthChange || isHeightChange) {
|
||||
change.width =
|
||||
isWidthChange && (!resizeDirection || resizeDirection === 'horizontal') ? width : prevValues.width;
|
||||
isWidthChange && (!params.resizeDirection || params.resizeDirection === 'horizontal')
|
||||
? width
|
||||
: prevValues.width;
|
||||
change.height =
|
||||
isHeightChange && (!resizeDirection || resizeDirection === 'vertical') ? height : prevValues.height;
|
||||
isHeightChange && (!params.resizeDirection || params.resizeDirection === 'vertical')
|
||||
? height
|
||||
: prevValues.height;
|
||||
prevValues.width = change.width;
|
||||
prevValues.height = change.height;
|
||||
}
|
||||
@@ -291,8 +313,8 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
|
||||
prevWidth,
|
||||
height: prevValues.height,
|
||||
prevHeight,
|
||||
affectsX: controlDirection.affectsX,
|
||||
affectsY: controlDirection.affectsY,
|
||||
affectsX: params.controlDirection.affectsX,
|
||||
affectsY: params.controlDirection.affectsY,
|
||||
});
|
||||
|
||||
const nextValues = { ...prevValues, direction };
|
||||
|
||||
Reference in New Issue
Block a user