feat: implement node sockets ui
📊 Benchmark the Runtime / benchmark (pull_request) Successful in 1m22s
🚀 Lint & Test & Deploy / quality (pull_request) Failing after 1m6s
🚀 Lint & Test & Deploy / test-unit (pull_request) Failing after 43s
🚀 Lint & Test & Deploy / test-e2e (pull_request) Successful in 2m5s
🚀 Lint & Test & Deploy / deploy (pull_request) Has been skipped

This commit is contained in:
2026-05-05 21:07:57 +02:00
parent ed11195327
commit 7f082ad8f6
12 changed files with 331 additions and 40 deletions
@@ -51,7 +51,7 @@ export class GraphManager extends EventEmitter<{
id: number;
nodes: SerializedNode[];
edges: SerializedEdge[];
cameraPosition: [number, number, number];
nodeId: number; // group instance node id that was entered to reach the next level
}[] = $state([]);
// ID of the currently active group, or null when at the root graph.
@@ -642,11 +642,11 @@ export class GraphManager extends EventEmitter<{
isInsideGroup = $derived(this.currentGroupId !== null);
enterGroup(nodeId: number, cameraPosition: [number, number, number]): boolean {
enterGroup(nodeId: number): boolean {
const groupNode = this.getNode(nodeId);
if (!groupNode || groupNode.type !== '__internal/group/instance') return false;
log.log('entering group', { nodeId, cameraPosition });
log.log('entering group', { nodeId });
const groupId = groupNode.props?.groupId as number;
const group = this.getGroup(groupId);
@@ -657,7 +657,7 @@ export class GraphManager extends EventEmitter<{
id: this.currentGroupId ?? this.id,
nodes: [...this.nodes.values()].map(n => serializeNode(n)),
edges: [...this.edges.values()].map(e => serializeEdge(e)),
cameraPosition
nodeId
});
this.currentGroupId = groupId;
@@ -685,6 +685,8 @@ export class GraphManager extends EventEmitter<{
this.history.reset();
this.execute();
this.save();
return { nodeId: parent.nodeId };
}
createNodeId() {
@@ -365,7 +365,7 @@ export class GraphState {
if (this.activeNodeId === -1) return;
const node = this.graph.getNode(this.activeNodeId);
if (!node || node.type !== '__internal/group/instance') return;
const ok = this.graph.enterGroup(this.activeNodeId, [...this.cameraPosition]);
const ok = this.graph.enterGroup(this.activeNodeId);
if (ok) {
this.activeNodeId = -1;
this.clearSelection();
@@ -375,7 +375,6 @@ export class GraphState {
exitGroupNode() {
const result = this.graph.exitGroup();
if (!result) return;
this.cameraPosition = result.camera;
this.activeNodeId = result.nodeId;
this.clearSelection();
}
+9 -1
View File
@@ -2,7 +2,7 @@ type Color = { hue: number; saturation: number; lightness: number };
export class ColorGenerator {
private colors: Map<string, Color> = new Map();
private lightnessLevels = [10, 60];
// private lightnessLevels = [10, 60];
constructor(predefined: Record<string, Color>) {
for (const [id, colorStr] of Object.entries(predefined)) {
@@ -10,6 +10,14 @@ export class ColorGenerator {
}
}
public getColors() {
return Object.fromEntries(
this.colors.entries().map(([key, col]) => {
return [key, this.colorToHsl(col)];
})
);
}
public getColor(id: string): string {
if (this.colors.has(id)) {
return this.colorToHsl(this.colors.get(id)!);
@@ -26,6 +26,13 @@
const rightBump = $derived(
!!nodeType?.outputs?.length && node.type !== '__internal/group/input'
);
const cornerBottom = $derived(
node.type === '__internal/group/input'
? (Object.keys(nodeType?.inputs ?? {}).length ? 0 : 10)
: node.type === '__internal/group/output'
? (nodeType?.outputs?.length ? 0 : 10)
: 0
);
const aspectRatio = 0.25;
@@ -35,6 +42,7 @@
height: 34,
y: 49,
cornerTop,
cornerBottom,
rightBump,
aspectRatio
})
@@ -45,6 +53,7 @@
height: 40,
y: 49,
cornerTop,
cornerBottom,
rightBump,
aspectRatio
})