Skip to content

Commit c434a70

Browse files
committed
feat: Lock Flex Nodes
1 parent 2f65556 commit c434a70

3 files changed

Lines changed: 62 additions & 9 deletions

File tree

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

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import {
55
type ResizeDragEvent,
66
type ResizeParams,
77
} from "@xyflow/react";
8-
import { useEffect, useState } from "react";
8+
import { type MouseEvent, useEffect, useState } from "react";
99

10+
import { Button } from "@/components/ui/button";
11+
import { Icon } from "@/components/ui/icon";
1012
import { BlockStack } from "@/components/ui/layout";
1113
import { Paragraph } from "@/components/ui/typography";
1214
import { cn } from "@/lib/utils";
@@ -24,7 +26,7 @@ type FlexNodeProps = NodeProps<Node<FlexNodeData>>;
2426
const MIN_SIZE = { width: 50, height: 50 };
2527

2628
const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
27-
const { properties, readOnly } = data;
29+
const { properties, readOnly, locked } = data;
2830
const { title, content, color, borderColor } = properties;
2931

3032
const [isInlineEditing, setIsInlineEditing] = useState(false);
@@ -42,6 +44,39 @@ const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
4244
setComponentSpec,
4345
} = useComponentSpec();
4446

47+
const toggleLock = () => {
48+
const updatedSubgraphSpec = updateFlexNodeInComponentSpec(
49+
currentSubgraphSpec,
50+
{
51+
...data,
52+
locked: !locked,
53+
},
54+
);
55+
56+
const newRootSpec = updateSubgraphSpec(
57+
componentSpec,
58+
currentSubgraphPath,
59+
updatedSubgraphSpec,
60+
);
61+
62+
setComponentSpec(newRootSpec);
63+
};
64+
65+
const handleLockToggle = (e: MouseEvent<HTMLButtonElement>) => {
66+
e.stopPropagation();
67+
toggleLock();
68+
};
69+
70+
const handleDoubleClick = () => {
71+
if (locked) {
72+
toggleLock();
73+
return;
74+
}
75+
if (!readOnly) {
76+
setIsInlineEditing(true);
77+
}
78+
};
79+
4580
const handleResizeEnd = (_: ResizeDragEvent, params: ResizeParams) => {
4681
const width = Math.max(params.width, MIN_SIZE.width);
4782
const height = Math.max(params.height, MIN_SIZE.height);
@@ -116,7 +151,7 @@ const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
116151
<div
117152
key={id}
118153
className={cn(
119-
"p-1 rounded-lg h-full w-full",
154+
"p-1 rounded-lg h-full w-full group",
120155
readOnly && selected && "ring-2 ring-ring",
121156
isTransparent && "border-2 border-solid",
122157
isTransparent &&
@@ -129,18 +164,33 @@ const FlexNode = ({ data, id, selected }: FlexNodeProps) => {
129164
backgroundColor: color,
130165
borderColor: isTransparent ? borderColor : undefined,
131166
}}
132-
onDoubleClick={() => setIsInlineEditing(true)}
167+
onDoubleClick={handleDoubleClick}
133168
>
134169
<div
135170
className={cn(
136171
"rounded-sm p-1 h-full w-full overflow-hidden",
137172
isTransparent ? "bg-transparent" : "bg-white/40",
138173
)}
139174
>
140-
<BlockStack gap="1">
141-
<Paragraph size="sm" weight="semibold">
142-
{title}
143-
</Paragraph>
175+
<BlockStack gap="1" className="w-full">
176+
<Button
177+
variant="ghost"
178+
size="min"
179+
onClick={handleLockToggle}
180+
className={cn(
181+
"absolute top-1 right-1 opacity-50 hover:bg-transparent hover:opacity-100",
182+
!locked && "hidden group-hover:block",
183+
)}
184+
>
185+
<Icon name={locked ? "Lock" : "LockOpen"} className="w-2! h-2!" />
186+
</Button>
187+
188+
{title && (
189+
<Paragraph size="sm" weight="semibold">
190+
{title}
191+
</Paragraph>
192+
)}
193+
144194
{isInlineEditing ? (
145195
<InlineTextEditor
146196
value={content}

src/components/shared/ReactFlow/FlowCanvas/FlexNode/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface FlexNodeData extends Record<string, unknown> {
88
position: XYPosition;
99
zIndex: number;
1010
readOnly?: boolean;
11+
locked?: boolean;
1112
}
1213

1314
type FlexNodeProperties = {

src/components/shared/ReactFlow/FlowCanvas/FlexNode/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const createFlexNode = (
1515
flexNode: FlexNodeData,
1616
readOnly: boolean = false,
1717
) => {
18-
const { id, position, size, zIndex } = flexNode;
18+
const { id, position, size, zIndex, locked } = flexNode;
1919

2020
return {
2121
id,
@@ -25,5 +25,7 @@ export const createFlexNode = (
2525
type: "flex",
2626
connectable: false,
2727
zIndex,
28+
selectable: !locked,
29+
draggable: !locked,
2830
} as Node;
2931
};

0 commit comments

Comments
 (0)