Skip to content

Commit 67775fc

Browse files
committed
feat: zIndex Management for IO Nodes
1 parent ee6ff89 commit 67775fc

File tree

7 files changed

+168
-14
lines changed

7 files changed

+168
-14
lines changed

react-compiler.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const REACT_COMPILER_ENABLED_DIRS = [
4747
"src/components/shared/TaskDetails/DisplayNameEditor.tsx",
4848
"src/components/shared/TaskDetails/Actions/UnpackSubgraphButton.tsx",
4949
"src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/ZIndexEditor.tsx",
50+
"src/components/Editor/IOEditor/IOZIndexEditor.tsx",
5051

5152
// 11-20 useCallback/useMemo
5253
// "src/components/ui", // 12
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { ContentBlock } from "@/components/shared/ContextPanel/Blocks/ContentBlock";
2+
import { StackingControls } from "@/components/shared/ReactFlow/FlowControls/StackingControls";
3+
import { useComponentSpec } from "@/providers/ComponentSpecProvider";
4+
import { ZINDEX_ANNOTATION } from "@/utils/annotations";
5+
import {
6+
type ComponentSpec,
7+
type InputSpec,
8+
isInputSpec,
9+
isOutputSpec,
10+
type OutputSpec,
11+
} from "@/utils/componentSpec";
12+
import {
13+
inputNameToNodeId,
14+
outputNameToNodeId,
15+
} from "@/utils/nodes/nodeIdUtils";
16+
import { updateSubgraphSpec } from "@/utils/subgraphUtils";
17+
18+
interface IOZIndexEditorProps {
19+
ioSpec: InputSpec | OutputSpec;
20+
}
21+
22+
export const IOZIndexEditor = ({ ioSpec }: IOZIndexEditorProps) => {
23+
const {
24+
componentSpec,
25+
currentSubgraphSpec,
26+
currentSubgraphPath,
27+
setComponentSpec,
28+
} = useComponentSpec();
29+
30+
const isInput = isInputSpec(ioSpec);
31+
32+
const nodeId = isInput
33+
? inputNameToNodeId(ioSpec.name)
34+
: outputNameToNodeId(ioSpec.name);
35+
36+
const handleStackingControlChange = (newZIndex: number) => {
37+
const updatedSubgraphSpec = setZIndexInAnnotations(
38+
currentSubgraphSpec,
39+
ioSpec,
40+
newZIndex,
41+
);
42+
43+
const newRootSpec = updateSubgraphSpec(
44+
componentSpec,
45+
currentSubgraphPath,
46+
updatedSubgraphSpec,
47+
);
48+
49+
setComponentSpec(newRootSpec);
50+
};
51+
52+
return (
53+
<ContentBlock className="border rounded-lg p-2 bg-background w-fit mx-auto">
54+
<StackingControls
55+
nodeId={nodeId}
56+
onChange={handleStackingControlChange}
57+
/>
58+
</ContentBlock>
59+
);
60+
};
61+
62+
function setZIndexInAnnotations(
63+
componentSpec: ComponentSpec,
64+
ioSpec: InputSpec | OutputSpec,
65+
zIndex: number,
66+
): ComponentSpec {
67+
const newComponentSpec = { ...componentSpec };
68+
69+
const isInput = isInputSpec(ioSpec);
70+
const isOutput = isOutputSpec(ioSpec);
71+
72+
if (isInput) {
73+
const inputs = [...(newComponentSpec.inputs || [])];
74+
const inputIndex = inputs.findIndex((input) => input.name === ioSpec.name);
75+
76+
if (inputIndex >= 0) {
77+
const annotations = inputs[inputIndex].annotations || {};
78+
79+
const updatedAnnotations = {
80+
...annotations,
81+
[ZINDEX_ANNOTATION]: `${zIndex}`,
82+
};
83+
84+
inputs[inputIndex] = {
85+
...inputs[inputIndex],
86+
annotations: updatedAnnotations,
87+
};
88+
89+
newComponentSpec.inputs = inputs;
90+
}
91+
} else if (isOutput) {
92+
const outputs = [...(newComponentSpec.outputs || [])];
93+
const outputIndex = outputs.findIndex(
94+
(output) => output.name === ioSpec.name,
95+
);
96+
97+
if (outputIndex >= 0) {
98+
const annotations = outputs[outputIndex].annotations || {};
99+
100+
const updatedAnnotations = {
101+
...annotations,
102+
[ZINDEX_ANNOTATION]: `${zIndex}`,
103+
};
104+
105+
outputs[outputIndex] = {
106+
...outputs[outputIndex],
107+
annotations: updatedAnnotations,
108+
};
109+
110+
newComponentSpec.outputs = outputs;
111+
}
112+
}
113+
114+
return newComponentSpec;
115+
}

src/components/Editor/IOEditor/InputValueEditor/InputValueEditor.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { InfoBox } from "@/components/shared/InfoBox";
66
import { removeGraphInput } from "@/components/shared/ReactFlow/FlowCanvas/utils/removeNode";
77
import { Button } from "@/components/ui/button";
88
import { Icon } from "@/components/ui/icon";
9-
import { BlockStack } from "@/components/ui/layout";
9+
import { BlockStack, InlineStack } from "@/components/ui/layout";
1010
import { Heading, Paragraph } from "@/components/ui/typography";
1111
import useConfirmationDialog from "@/hooks/useConfirmationDialog";
1212
import { useNodeSelectionTransfer } from "@/hooks/useNodeSelectionTransfer";
@@ -18,6 +18,7 @@ import { checkInputConnectionToRequiredFields } from "@/utils/inputConnectionUti
1818
import { inputNameToNodeId } from "@/utils/nodes/nodeIdUtils";
1919
import { updateSubgraphSpec } from "@/utils/subgraphUtils";
2020

21+
import { IOZIndexEditor } from "../IOZIndexEditor";
2122
import {
2223
DescriptionField,
2324
NameField,
@@ -318,11 +319,15 @@ export const InputValueEditor = ({
318319
</InfoBox>
319320
)}
320321

321-
{!disabled && (
322-
<Button onClick={deleteNode} variant="destructive" size="icon">
323-
<Icon name="Trash2" />
324-
</Button>
325-
)}
322+
<InlineStack gap="4">
323+
{!disabled && (
324+
<Button onClick={deleteNode} variant="destructive" size="icon">
325+
<Icon name="Trash2" />
326+
</Button>
327+
)}
328+
329+
<IOZIndexEditor ioSpec={input} />
330+
</InlineStack>
326331

327332
<ConfirmationDialog
328333
{...confirmationProps}

src/components/Editor/IOEditor/OutputNameEditor/OutputNameEditor.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ConfirmationDialog from "@/components/shared/Dialogs/ConfirmationDialog";
44
import { removeGraphOutput } from "@/components/shared/ReactFlow/FlowCanvas/utils/removeNode";
55
import { Button } from "@/components/ui/button";
66
import { Icon } from "@/components/ui/icon";
7-
import { BlockStack } from "@/components/ui/layout";
7+
import { BlockStack, InlineStack } from "@/components/ui/layout";
88
import { Heading, Paragraph } from "@/components/ui/typography";
99
import useConfirmationDialog from "@/hooks/useConfirmationDialog";
1010
import { useNodeSelectionTransfer } from "@/hooks/useNodeSelectionTransfer";
@@ -22,6 +22,7 @@ import {
2222
TypeField,
2323
} from "../InputValueEditor/FormFields";
2424
import { checkNameCollision } from "../InputValueEditor/FormFields/utils";
25+
import { IOZIndexEditor } from "../IOZIndexEditor";
2526

2627
interface OutputNameEditorProps {
2728
output: OutputSpec;
@@ -206,11 +207,15 @@ export const OutputNameEditor = ({
206207
/>
207208
</div>
208209

209-
{!disabled && (
210-
<Button onClick={deleteNode} variant="destructive" size="icon">
211-
<Icon name="Trash2" />
212-
</Button>
213-
)}
210+
<InlineStack gap="4">
211+
{!disabled && (
212+
<Button onClick={deleteNode} variant="destructive" size="icon">
213+
<Icon name="Trash2" />
214+
</Button>
215+
)}
216+
217+
<IOZIndexEditor ioSpec={output} />
218+
</InlineStack>
214219

215220
<ConfirmationDialog
216221
{...confirmationProps}

src/utils/componentSpec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,19 @@ export const isGraphInputArgument = (
529529
arg?: ArgumentType,
530530
): arg is GraphInputArgument =>
531531
typeof arg === "object" && arg !== null && "graphInput" in arg;
532+
533+
export const isInputSpec = (obj: InputOutputSpec): obj is InputSpec =>
534+
typeof obj === "object" &&
535+
obj !== null &&
536+
"name" in obj &&
537+
typeof obj.name === "string" &&
538+
("default" in obj || "optional" in obj || "value" in obj);
539+
540+
export const isOutputSpec = (obj: InputOutputSpec): obj is OutputSpec =>
541+
typeof obj === "object" &&
542+
obj !== null &&
543+
"name" in obj &&
544+
typeof obj.name === "string" &&
545+
!("default" in obj) &&
546+
!("optional" in obj) &&
547+
!("value" in obj);

src/utils/nodes/createInputNode.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@ import type { TaskNodeData } from "@/types/taskNode";
44

55
import type { InputSpec } from "../componentSpec";
66
import { extractPositionFromAnnotations } from "./extractPositionFromAnnotations";
7+
import { extractZIndexFromAnnotations } from "./extractZIndexFromAnnotations";
78
import { inputNameToNodeId } from "./nodeIdUtils";
89

910
export const createInputNode = (
1011
input: InputSpec,
1112
nodeData: TaskNodeData,
1213
readOnly: boolean,
1314
) => {
15+
const nodeType = "input";
16+
1417
const { name, annotations, ...rest } = input;
1518

1619
const position = extractPositionFromAnnotations(annotations);
20+
const zIndex = extractZIndexFromAnnotations(input.annotations, nodeType);
21+
1722
const nodeId = inputNameToNodeId(name);
1823

1924
return {
@@ -25,6 +30,7 @@ export const createInputNode = (
2530
readOnly,
2631
},
2732
position: position,
28-
type: "input",
33+
type: nodeType,
34+
zIndex,
2935
} as Node;
3036
};

src/utils/nodes/createOutputNode.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@ import type { TaskNodeData } from "@/types/taskNode";
44

55
import type { OutputSpec } from "../componentSpec";
66
import { extractPositionFromAnnotations } from "./extractPositionFromAnnotations";
7+
import { extractZIndexFromAnnotations } from "./extractZIndexFromAnnotations";
78
import { outputNameToNodeId } from "./nodeIdUtils";
89

910
export const createOutputNode = (
1011
output: OutputSpec,
1112
nodeData: TaskNodeData,
1213
readOnly: boolean,
1314
) => {
15+
const nodeType = "output";
16+
1417
const { name, annotations, ...rest } = output;
1518

1619
const position = extractPositionFromAnnotations(annotations);
20+
const zIndex = extractZIndexFromAnnotations(output.annotations, nodeType);
21+
1722
const nodeId = outputNameToNodeId(name);
1823

1924
return {
@@ -25,6 +30,7 @@ export const createOutputNode = (
2530
readOnly,
2631
},
2732
position: position,
28-
type: "output",
33+
type: nodeType,
34+
zIndex,
2935
} as Node;
3036
};

0 commit comments

Comments
 (0)