feat: added rule based connection validation and connection limits to the editor

This commit is contained in:
Gerla, J. (Justin)
2026-01-07 13:32:53 +00:00
committed by Björn Otgaar
parent 6d1c17e77b
commit 9e7c192804
20 changed files with 672 additions and 89 deletions

View File

@@ -0,0 +1,88 @@
import {
Handle,
type HandleProps,
type Connection,
useNodeId, useNodeConnections
} from '@xyflow/react';
import {useState} from 'react';
import { type HandleRule, useHandleRules} from "../HandleRuleLogic.ts";
import "./RuleBasedHandle.module.css";
export function MultiConnectionHandle({
id,
type,
rules = [],
...otherProps
} : HandleProps & { rules?: HandleRule[]}) {
let nodeId = useNodeId();
// this check is used to make sure that the handle code doesn't break when used inside a test,
// since useNodeId would be undefined if the handle is not used inside a node
nodeId = nodeId ? nodeId : "mockId";
const validate = useHandleRules(nodeId, id!, type!, rules);
const connections = useNodeConnections({
id: nodeId,
handleType: type,
handleId: id!
})
// initialise the handles state with { isValid: true } to show that connections are possible
const [handleState, setHandleState] = useState<{ isSatisfied: boolean, message?: string }>({ isSatisfied: true });
return (
<Handle
{...otherProps}
id={id}
type={type}
className={"multiConnectionHandle" + (connections.length === 0 ? " unconnected" : " connected")}
isValidConnection={(connection) => {
const result = validate(connection as Connection);
setHandleState(result);
return result.isSatisfied;
}}
title={handleState.message}
/>
);
}
export function SingleConnectionHandle({
id,
type,
rules = [],
...otherProps
} : HandleProps & { rules?: HandleRule[]}) {
let nodeId = useNodeId();
// this check is used to make sure that the handle code doesn't break when used inside a test,
// since useNodeId would be undefined if the handle is not used inside a node
nodeId = nodeId ? nodeId : "mockId";
const validate = useHandleRules(nodeId, id!, type!, rules);
const connections = useNodeConnections({
id: nodeId,
handleType: type,
handleId: id!
})
// initialise the handles state with { isValid: true } to show that connections are possible
const [handleState, setHandleState] = useState<{ isSatisfied: boolean, message?: string }>({ isSatisfied: true });
return (
<Handle
{...otherProps}
id={id}
type={type}
className={"singleConnectionHandle" + (connections.length === 0 ? " unconnected" : " connected")}
isConnectable={connections.length === 0}
isValidConnection={(connection) => {
const result = validate(connection as Connection);
setHandleState(result);
return result.isSatisfied;
}}
title={handleState.message}
/>
);
}