Skip to content

Commit f6aee4b

Browse files
committed
feat: Resizable Flex Nodes
1 parent 3e8f224 commit f6aee4b

File tree

1 file changed

+69
-19
lines changed
  • src/components/shared/ReactFlow/FlowCanvas/FlexNode

1 file changed

+69
-19
lines changed

src/components/shared/ReactFlow/FlowCanvas/FlexNode/FlexNode.tsx

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
1-
import { type Node, type NodeProps } from "@xyflow/react";
1+
import {
2+
type Node,
3+
type NodeProps,
4+
NodeResizer,
5+
type ResizeDragEvent,
6+
type ResizeParams,
7+
} from "@xyflow/react";
28
import { useEffect } from "react";
39

410
import { BlockStack } from "@/components/ui/layout";
511
import { Paragraph } from "@/components/ui/typography";
612
import { cn } from "@/lib/utils";
13+
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
714
import { useContextPanel } from "@/providers/ContextPanelProvider";
15+
import { updateSubgraphSpec } from "@/utils/subgraphUtils";
816

917
import { FlexNodeEditor } from "./FlexNodeEditor";
18+
import { updateFlexNodeInComponentSpec } from "./interface";
1019
import type { FlexNodeData } from "./types";
1120

1221
type FlexNodeProps = NodeProps<Node<FlexNodeData>>;
1322

23+
const MIN_SIZE = { width: 50, height: 50 };
24+
1425
const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
1526
const { properties, readOnly } = data;
1627
const { title, content, color } = properties;
@@ -21,6 +32,34 @@ const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
2132
setOpen: setContextPanelOpen,
2233
} = useContextPanel();
2334

35+
const {
36+
currentSubgraphSpec,
37+
currentSubgraphPath,
38+
componentSpec,
39+
setComponentSpec,
40+
} = useComponentSpec();
41+
42+
const handleResizeEnd = (_: ResizeDragEvent, params: ResizeParams) => {
43+
const width = Math.max(params.width, MIN_SIZE.width);
44+
const height = Math.max(params.height, MIN_SIZE.height);
45+
46+
const updatedSubgraphSpec = updateFlexNodeInComponentSpec(
47+
currentSubgraphSpec,
48+
{
49+
...data,
50+
size: { width, height },
51+
},
52+
);
53+
54+
const newRootSpec = updateSubgraphSpec(
55+
componentSpec,
56+
currentSubgraphPath,
57+
updatedSubgraphSpec,
58+
);
59+
60+
setComponentSpec(newRootSpec);
61+
};
62+
2463
useEffect(() => {
2564
if (selected) {
2665
setContent(<FlexNodeEditor flexNode={data} readOnly={readOnly} />);
@@ -37,29 +76,40 @@ const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
3776
const isTransparent = color === "transparent";
3877

3978
return (
40-
<div
41-
key={id}
42-
className={cn(
43-
"p-1 rounded-lg border-2 border-transparent h-full w-full",
44-
isTransparent && !title && !content && "border-dashed border-warning",
45-
selected && "border-gray-500 border-solid",
46-
)}
47-
style={{ backgroundColor: color }}
48-
>
79+
<>
80+
<NodeResizer
81+
color="var(--edge-selected)"
82+
isVisible={selected}
83+
minWidth={50}
84+
minHeight={50}
85+
onResizeEnd={handleResizeEnd}
86+
/>
4987
<div
88+
key={id}
5089
className={cn(
51-
"rounded-sm p-1 h-full w-full overflow-hidden",
52-
isTransparent ? "bg-transparent" : "bg-white/40",
90+
"p-1 rounded-lg h-full w-full",
91+
isTransparent &&
92+
!title &&
93+
!content &&
94+
"border-2 border-dashed border-warning",
5395
)}
96+
style={{ backgroundColor: color }}
5497
>
55-
<BlockStack gap="1">
56-
<Paragraph size="sm" weight="semibold">
57-
{title}
58-
</Paragraph>
59-
<Paragraph size="xs">{content}</Paragraph>
60-
</BlockStack>
98+
<div
99+
className={cn(
100+
"rounded-sm p-1 h-full w-full overflow-hidden",
101+
isTransparent ? "bg-transparent" : "bg-white/40",
102+
)}
103+
>
104+
<BlockStack gap="1">
105+
<Paragraph size="sm" weight="semibold">
106+
{title}
107+
</Paragraph>
108+
<Paragraph size="xs">{content}</Paragraph>
109+
</BlockStack>
110+
</div>
61111
</div>
62-
</div>
112+
</>
63113
);
64114
};
65115

0 commit comments

Comments
 (0)