feat(node-resizer): add flag to keep aspect ratio, cleanup example

This commit is contained in:
Christopher Möller
2023-03-07 16:41:15 +01:00
parent 5becbb1ebe
commit 8b0808ec03
12 changed files with 241 additions and 151 deletions
@@ -10,10 +10,21 @@ const controlStyle = {
border: 'none',
};
const CustomNode: FC<NodeProps> = ({ id, data }) => {
const CustomResizerNode: FC<NodeProps> = ({ data }) => {
return (
<>
<NodeResizeControl style={controlStyle}>
<NodeResizeControl
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
style={controlStyle}
>
<ResizeIcon />
</NodeResizeControl>
@@ -24,4 +35,4 @@ const CustomNode: FC<NodeProps> = ({ id, data }) => {
);
};
export default memo(CustomNode);
export default memo(CustomResizerNode);
@@ -1,19 +0,0 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizeControl } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const CustomNode: FC<NodeProps> = ({ id, data }) => {
return (
<>
<NodeResizeControl color="red" position={Position.Top} />
<NodeResizeControl color="red" position={Position.Bottom} />
<Handle type="target" position={Position.Left} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(CustomNode);
@@ -1,33 +0,0 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizeControl, OnResize, ShouldResize } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const shouldResize: ShouldResize = (event, params) => {
console.log('before resize', params);
if (params.width > 100) {
return false;
}
return true;
};
const onResize: OnResize = (event, params) => {
console.log('resize', params.direction);
};
const CustomNode: FC<NodeProps> = ({ id, data }) => {
return (
<>
<NodeResizeControl color="red" position={Position.Left} />
<NodeResizeControl color="red" position={Position.Right} shouldResize={shouldResize} onResize={onResize} />
<Handle type="target" position={Position.Top} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Bottom} />
</>
);
};
export default memo(CustomNode);
@@ -0,0 +1,29 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizer } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
return (
<>
<NodeResizer
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
isVisible={data.isVisible ?? selected}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
/>
<Handle type="target" position={Position.Left} />
<div>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(DefaultResizerNode);
@@ -0,0 +1,43 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizeControl } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const HorizontalResizerNode: FC<NodeProps> = ({ data }) => {
return (
<>
<NodeResizeControl
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
color="red"
position={Position.Left}
/>
<NodeResizeControl
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
color="red"
position={Position.Right}
/>
<Handle type="target" position={Position.Top} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Bottom} />
</>
);
};
export default memo(HorizontalResizerNode);
@@ -1,44 +0,0 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizer, ShouldResize, OnResize, OnResizeEnd, OnResizeStart } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const onResizeStart: OnResizeStart = (_, params) => {
console.log('resize start', params);
};
const onResize: OnResize = (_, params) => {
console.log('resize', params);
};
const onResizeEnd: OnResizeEnd = (_, params) => {
console.log('resize end', params);
};
const shouldResize: ShouldResize = (_, params) => {
console.log('should resize', params);
return true;
};
const CustomNode: FC<NodeProps> = ({ data, selected }) => {
return (
<>
<NodeResizer
minWidth={100}
minHeight={100}
isVisible={selected}
shouldResize={shouldResize}
onResizeStart={onResizeStart}
onResize={onResize}
onResizeEnd={onResizeEnd}
/>
<Handle type="target" position={Position.Left} />
<div>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(CustomNode);
@@ -0,0 +1,43 @@
import { memo, FC } from 'react';
import { Handle, Position, NodeProps } from 'reactflow';
import { NodeResizeControl } from '@reactflow/node-resizer';
import '@reactflow/node-resizer/dist/style.css';
const CustomNode: FC<NodeProps> = ({ id, data }) => {
return (
<>
<NodeResizeControl
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
color="red"
position={Position.Top}
/>
<NodeResizeControl
minWidth={data.minWidth ?? undefined}
maxWidth={data.maxWidth ?? undefined}
minHeight={data.minHeight ?? undefined}
maxHeight={data.maxHeight ?? undefined}
shouldResize={data.shouldResize ?? undefined}
onResizeStart={data.onResizeStart ?? undefined}
onResize={data.onResize ?? undefined}
onResizeEnd={data.onResizeEnd ?? undefined}
keepAspectRatio={data.keepAspectRatio ?? undefined}
color="red"
position={Position.Bottom}
/>
<Handle type="target" position={Position.Left} />
<div style={{ padding: 10 }}>{data.label}</div>
<Handle type="source" position={Position.Right} />
</>
);
};
export default memo(CustomNode);
@@ -1,73 +1,97 @@
import { useCallback, useState } from 'react';
import ReactFlow, { Controls, addEdge, Position, Connection, useNodesState, useEdgesState, Panel } from 'reactflow';
import ReactFlow, { Controls, addEdge, Connection, useNodesState, useEdgesState, Panel, Node, Edge } from 'reactflow';
import NodeResizerNode from './NodeResizerNode';
import DefaultResizer from './DefaultResizer';
import CustomResizer from './CustomResizer';
import CustomResizer2 from './CustomResizer2';
import CustomResizer3 from './CustomResizer3';
import VerticalResizer from './VerticalResizer';
import HorizontalResizer from './HorizontalResizer';
const nodeTypes = {
resizer: NodeResizerNode,
defaultResizer: DefaultResizer,
customResizer: CustomResizer,
customResizer2: CustomResizer2,
customResizer3: CustomResizer3,
verticalResizer: VerticalResizer,
horizontalResizer: HorizontalResizer,
};
const initialEdges = [
{
id: 'e1-2',
source: '1',
target: '2',
},
];
const nodeStyle = {
border: '1px solid #222',
fontSize: 10,
backgroundColor: '#ddd',
};
const initialNodes = [
const initialEdges: Edge[] = [];
const initialNodes: Node[] = [
{
id: '1',
type: 'input',
data: { label: 'An input node' },
type: 'defaultResizer',
data: { label: 'default resizer' },
position: { x: 0, y: 0 },
sourcePosition: Position.Right,
style: { ...nodeStyle },
},
{
id: '2',
type: 'resizer',
data: { label: 'default resizer' },
id: '1a',
type: 'defaultResizer',
data: {
label: 'default resizer with min and max dimensions',
minWidth: 100,
minHeight: 80,
maxWidth: 200,
maxHeight: 200,
},
position: { x: 0, y: 60 },
style: { ...nodeStyle, width: 100, height: 80 },
},
{
id: '1b',
type: 'defaultResizer',
data: { label: 'default resizer with initial size and aspect ratio', keepAspectRatio: true },
position: { x: 250, y: 0 },
style: {
width: 200,
height: 150,
border: '1px solid #222',
fontSize: 10,
width: 174,
height: 123,
...nodeStyle,
},
},
{
id: '3',
id: '2',
type: 'customResizer',
data: { label: 'resize control with child component' },
data: { label: 'custom resize icon' },
position: { x: 0, y: 200 },
style: { width: 100, height: 60, ...nodeStyle },
},
{
id: '3',
type: 'verticalResizer',
data: { label: 'vertical resizer' },
position: { x: 250, y: 200 },
style: { border: '1px solid #222', fontSize: 10, width: 100 },
style: { ...nodeStyle },
},
{
id: '3a',
type: 'verticalResizer',
data: {
label: 'vertical resizer with min/maxHeight and aspect ratio',
minHeight: 50,
maxHeight: 200,
keepAspectRatio: true,
},
position: { x: 400, y: 200 },
style: { ...nodeStyle, height: 50 },
},
{
id: '4',
type: 'customResizer2',
data: { label: 'resize controls' },
position: { x: 100, y: 150 },
style: { border: '1px solid #222', fontSize: 10 },
type: 'horizontalResizer',
data: { label: 'horizontal resizer with aspect ratio', keepAspectRatio: true },
position: { x: 250, y: 300 },
style: { ...nodeStyle },
},
{
id: '5',
type: 'customResizer2',
data: { label: 'min width and height' },
position: { x: 250, y: 250 },
style: { border: '1px solid #222', fontSize: 10 },
},
{
id: '6',
type: 'customResizer3',
data: { label: 'resize controls' },
position: { x: 400, y: 200 },
style: { border: '1px solid #222', fontSize: 10 },
id: '4a',
type: 'horizontalResizer',
data: { label: 'horizontal resizer with maxWidth', maxWidth: 300 },
position: { x: 250, y: 400 },
style: { ...nodeStyle },
},
];