refactor(useConnection): return internal node, add node generic
This commit is contained in:
@@ -3,7 +3,19 @@ import { ReactFlow, Background, BackgroundVariant, Node, Edge, SelectionMode, Co
|
||||
const MULTI_SELECT_KEY = ['Meta', 'Shift'];
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, className: 'light' },
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: {
|
||||
label: (
|
||||
<>
|
||||
<input defaultValue="hallo"></input>
|
||||
</>
|
||||
),
|
||||
},
|
||||
position: { x: 250, y: 5 },
|
||||
className: 'light',
|
||||
},
|
||||
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 }, className: 'light' },
|
||||
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 }, className: 'light' },
|
||||
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 }, className: 'light' },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FC } from 'react';
|
||||
import { getBezierPath, ConnectionLineComponentProps, Node } from '@xyflow/react';
|
||||
import { getBezierPath, ConnectionLineComponentProps, Node, InternalNode } from '@xyflow/react';
|
||||
|
||||
import { getEdgeParams } from './utils';
|
||||
|
||||
@@ -13,7 +13,7 @@ const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({ toX, toY, fr
|
||||
width: 1,
|
||||
height: 1,
|
||||
position: { x: toX, y: toY },
|
||||
} as Node;
|
||||
} as InternalNode;
|
||||
|
||||
const { sx, sy } = getEdgeParams(fromNode, targetNode);
|
||||
|
||||
|
||||
@@ -2,21 +2,19 @@ import { Position, XYPosition, Node, Edge, InternalNode } from '@xyflow/react';
|
||||
|
||||
// this helper function returns the intersection point
|
||||
// of the line between the center of the intersectionNode and the target node
|
||||
function getNodeIntersection(intersectionNode: Node, targetNode: Node): XYPosition {
|
||||
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
|
||||
|
||||
const { position: intersectionNodePosition } = intersectionNode;
|
||||
function getNodeIntersection(intersectionNode: InternalNode, targetNode: InternalNode): XYPosition {
|
||||
const { internals: intersectionInternals } = intersectionNode;
|
||||
const { width: intersectionNodeWidth, height: intersectionNodeHeight } = intersectionNode.measured ?? {
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
const targetPosition = targetNode.position;
|
||||
const targetPosition = targetNode.internals.positionAbsolute;
|
||||
|
||||
const w = (intersectionNodeWidth ?? 0) / 2;
|
||||
const h = (intersectionNodeHeight ?? 0) / 2;
|
||||
|
||||
const x2 = intersectionNodePosition.x + w;
|
||||
const y2 = intersectionNodePosition.y + h;
|
||||
const x2 = intersectionInternals.positionAbsolute.x + w;
|
||||
const y2 = intersectionInternals.positionAbsolute.y + h;
|
||||
const x1 = targetPosition.x + w;
|
||||
const y1 = targetPosition.y + h;
|
||||
|
||||
@@ -92,7 +90,13 @@ export function createElements(): NodesAndEdges {
|
||||
const x = 250 * Math.cos(radians) + center.x;
|
||||
const y = 250 * Math.sin(radians) + center.y;
|
||||
|
||||
nodes.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } });
|
||||
const isChild = i === 1;
|
||||
nodes.push({
|
||||
id: `${i}`,
|
||||
data: { label: 'Source' },
|
||||
position: isChild ? { x: 0, y: 0 } : { x, y },
|
||||
parentId: isChild ? '0' : undefined,
|
||||
});
|
||||
|
||||
edges.push({
|
||||
id: `edge-${i}`,
|
||||
|
||||
@@ -40,7 +40,7 @@ const initialEdges: Edge[] = [
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
];
|
||||
|
||||
const UseZoomPanHelperFlow = () => {
|
||||
const UseConnectionFlow = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
@@ -68,7 +68,7 @@ const UseZoomPanHelperFlow = () => {
|
||||
|
||||
const WrappedFlow = () => (
|
||||
<ReactFlowProvider>
|
||||
<UseZoomPanHelperFlow />
|
||||
<UseConnectionFlow />
|
||||
</ReactFlowProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { useStore } from './useStore';
|
||||
import type { ReactFlowStore } from '../types/store';
|
||||
import { ConnectionState, pointToRendererPoint } from '@xyflow/system';
|
||||
|
||||
const selector = (s: ReactFlowStore): ConnectionState => {
|
||||
import { useStore } from './useStore';
|
||||
import type { InternalNode, Node, ReactFlowStore } from '../types';
|
||||
|
||||
const selector = (s: ReactFlowStore) => {
|
||||
return s.connection.inProgress
|
||||
? { ...s.connection, to: pointToRendererPoint(s.connection.to, s.transform) }
|
||||
: { ...s.connection };
|
||||
@@ -15,6 +15,6 @@ const selector = (s: ReactFlowStore): ConnectionState => {
|
||||
* @public
|
||||
* @returns ConnectionState
|
||||
*/
|
||||
export function useConnection(): ConnectionState {
|
||||
return useStore(selector, shallow);
|
||||
export function useConnection<NodeType extends Node = Node>(): ConnectionState<InternalNode<NodeType>> {
|
||||
return useStore(selector, shallow) as ConnectionState<InternalNode<NodeType>>;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
OnError,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { EdgeTypes, Node } from '.';
|
||||
import { EdgeTypes, InternalNode, Node } from '.';
|
||||
|
||||
export type EdgeLabelOptions = {
|
||||
label?: string | ReactNode;
|
||||
@@ -190,10 +190,10 @@ export type SimpleBezierEdgeProps = EdgeComponentProps;
|
||||
|
||||
export type OnReconnect<EdgeType extends Edge = Edge> = (oldEdge: EdgeType, newConnection: Connection) => void;
|
||||
|
||||
export type ConnectionLineComponentProps = {
|
||||
export type ConnectionLineComponentProps<NodeType extends Node = Node> = {
|
||||
connectionLineStyle?: CSSProperties;
|
||||
connectionLineType: ConnectionLineType;
|
||||
fromNode: Node;
|
||||
fromNode: InternalNode<NodeType>;
|
||||
fromHandle: Handle;
|
||||
fromX: number;
|
||||
fromY: number;
|
||||
@@ -202,8 +202,10 @@ export type ConnectionLineComponentProps = {
|
||||
fromPosition: Position;
|
||||
toPosition: Position;
|
||||
connectionStatus: 'valid' | 'invalid' | null;
|
||||
toNode: Node | null;
|
||||
toNode: InternalNode<NodeType> | null;
|
||||
toHandle: Handle | null;
|
||||
};
|
||||
|
||||
export type ConnectionLineComponent = ComponentType<ConnectionLineComponentProps>;
|
||||
export type ConnectionLineComponent<NodeType extends Node = Node> = ComponentType<
|
||||
ConnectionLineComponentProps<NodeType>
|
||||
>;
|
||||
|
||||
@@ -148,34 +148,30 @@ export const initialConnection: NoConnection = {
|
||||
export type NoConnection = {
|
||||
inProgress: false;
|
||||
isValid: null;
|
||||
|
||||
from: null;
|
||||
fromHandle: null;
|
||||
fromPosition: null;
|
||||
fromNode: null;
|
||||
|
||||
to: null;
|
||||
toHandle: null;
|
||||
toPosition: null;
|
||||
toNode: null;
|
||||
};
|
||||
|
||||
export type ConnectionInProgress = {
|
||||
export type ConnectionInProgress<NodeType extends InternalNodeBase = InternalNodeBase> = {
|
||||
inProgress: true;
|
||||
isValid: boolean | null;
|
||||
|
||||
from: XYPosition;
|
||||
fromHandle: Handle;
|
||||
fromPosition: Position;
|
||||
fromNode: NodeBase;
|
||||
|
||||
fromNode: NodeType;
|
||||
to: XYPosition;
|
||||
toHandle: Handle | null;
|
||||
toPosition: Position;
|
||||
toNode: NodeBase | null;
|
||||
toNode: NodeType | null;
|
||||
};
|
||||
|
||||
export type ConnectionState = ConnectionInProgress | NoConnection;
|
||||
export type ConnectionState<NodeType extends InternalNodeBase = InternalNodeBase> =
|
||||
| ConnectionInProgress<NodeType>
|
||||
| NoConnection;
|
||||
|
||||
export type UpdateConnection = (params: ConnectionState) => void;
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ function onPointerDown(
|
||||
from,
|
||||
fromHandle,
|
||||
fromPosition: fromHandle.position,
|
||||
fromNode: fromNodeInternal.internals.userNode,
|
||||
fromNode: fromNodeInternal,
|
||||
|
||||
to: position,
|
||||
toHandle: null,
|
||||
@@ -163,7 +163,7 @@ function onPointerDown(
|
||||
: position,
|
||||
toHandle: result.toHandle,
|
||||
toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
|
||||
toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)!.internals.userNode : null,
|
||||
toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId)! : null,
|
||||
};
|
||||
|
||||
// we don't want to trigger an update when the connection
|
||||
|
||||
Reference in New Issue
Block a user