refactor(types): cleanup

This commit is contained in:
moklick
2021-11-09 14:52:39 +01:00
parent a79e953ab3
commit 8a2ac1e31e
24 changed files with 655 additions and 667 deletions

View File

@@ -5,7 +5,7 @@ import shallow from 'zustand/shallow';
import { useStore } from '../../store';
import { getRectOfNodes } from '../../utils/graph';
import { getBoundsofRects } from '../../utils';
import { Node, Rect, ReactFlowState } from '../../types';
import { Node, ReactFlowState, Rect } from '../../types';
import MiniMapNode from './MiniMapNode';
type StringFunc = (node: Node) => string;

View File

@@ -5,20 +5,19 @@ import { useStore } from '../../store';
import { getBezierPath } from '../Edges/BezierEdge';
import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
import {
ElementId,
NodeInternalsItem,
HandleElement,
Position,
ConnectionLineType,
ConnectionLineComponent,
HandleType,
Node,
ReactFlowState,
Position,
} from '../../types';
interface ConnectionLineProps {
connectionNodeId: ElementId;
connectionHandleId: ElementId | null;
connectionNodeId: string;
connectionHandleId: string | null;
connectionHandleType: HandleType;
connectionPositionX: number;
connectionPositionY: number;

View File

@@ -3,16 +3,15 @@ import { MouseEvent as ReactMouseEvent } from 'react';
import { getHostForElement } from '../../utils';
import {
ElementId,
XYPosition,
OnConnectFunc,
OnConnectStartFunc,
OnConnectStopFunc,
OnConnectEndFunc,
OnConnect,
OnConnectStart,
OnConnectStop,
OnConnectEnd,
ConnectionMode,
SetConnectionId,
Connection,
HandleType,
XYPosition,
} from '../../types';
type ValidConnectionFunc = (connection: Connection) => boolean;
@@ -32,8 +31,8 @@ function checkElementBelowIsValid(
event: MouseEvent,
connectionMode: ConnectionMode,
isTarget: boolean,
nodeId: ElementId,
handleId: ElementId | null,
nodeId: string,
handleId: string | null,
isValidConnection: ValidConnectionFunc,
doc: Document | ShadowRoot
) {
@@ -91,19 +90,19 @@ function resetRecentHandle(hoveredHandle: Element): void {
export function onMouseDown(
event: ReactMouseEvent,
handleId: ElementId | null,
nodeId: ElementId,
handleId: string | null,
nodeId: string,
setConnectionNodeId: SetSourceIdFunc,
setPosition: SetPosition,
onConnect: OnConnectFunc,
onConnect: OnConnect,
isTarget: boolean,
isValidConnection: ValidConnectionFunc,
connectionMode: ConnectionMode,
elementEdgeUpdaterType?: HandleType,
onEdgeUpdateEnd?: (evt: MouseEvent) => void,
onConnectStart?: OnConnectStartFunc,
onConnectStop?: OnConnectStopFunc,
onConnectEnd?: OnConnectEndFunc
onConnectStart?: OnConnectStart,
onConnectStop?: OnConnectStop,
onConnectEnd?: OnConnectEnd
): void {
const reactFlowNode = (event.target as Element).closest('.react-flow');
// when react-flow is used inside a shadow root we can't use document

View File

@@ -4,7 +4,7 @@ import shallow from 'zustand/shallow';
import { useStore } from '../../store';
import NodeIdContext from '../../contexts/NodeIdContext';
import { HandleProps, Connection, ElementId, Position, ReactFlowState } from '../../types';
import { HandleProps, Connection, ReactFlowState, Position } from '../../types';
import { onMouseDown, SetSourceIdFunc, SetPosition } from './handler';
@@ -37,7 +37,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
},
ref
) => {
const nodeId = useContext(NodeIdContext) as ElementId;
const nodeId = useContext(NodeIdContext) as string;
const {
setPosition,
setConnectionNodeId,

View File

@@ -5,7 +5,7 @@ import shallow from 'zustand/shallow';
import { useStore } from '../../store';
import { Provider } from '../../contexts/NodeIdContext';
import { NodeComponentProps, WrapNodeProps, ReactFlowState } from '../../types';
import { NodeProps, WrapNodeProps, ReactFlowState } from '../../types';
const selector = (s: ReactFlowState) => ({
addSelectedElements: s.addSelectedElements,
@@ -15,7 +15,7 @@ const selector = (s: ReactFlowState) => ({
unselectNodesAndEdges: s.unselectNodesAndEdges,
});
export default (NodeComponent: ComponentType<NodeComponentProps>) => {
export default (NodeComponent: ComponentType<NodeProps>) => {
const NodeWrapper = ({
id,
type,

View File

@@ -6,10 +6,10 @@ import {
Node,
Edge,
ReactFlowState,
OnConnectFunc,
OnConnectStartFunc,
OnConnectStopFunc,
OnConnectEndFunc,
OnConnect,
OnConnectStart,
OnConnectStop,
OnConnectEnd,
CoordinateExtent,
OnNodesChange,
OnEdgesChange,
@@ -20,10 +20,10 @@ import {
interface StoreUpdaterProps {
nodes: Node[];
edges: Edge[];
onConnect?: OnConnectFunc;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: OnConnectStopFunc;
onConnectEnd?: OnConnectEndFunc;
onConnect?: OnConnect;
onConnectStart?: OnConnectStart;
onConnectStop?: OnConnectStop;
onConnectEnd?: OnConnectEnd;
nodesDraggable?: boolean;
nodesConnectable?: boolean;
minZoom?: number;

View File

@@ -4,7 +4,7 @@ import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '../../compon
import wrapEdge from '../../components/Edges/wrapEdge';
import { rectToBox } from '../../utils';
import { EdgeTypesType, EdgeProps, Position, XYPosition, ElementId, HandleElement, Transform, Rect } from '../../types';
import { EdgeTypesType, EdgeProps, HandleElement, Position, XYPosition, Transform, Rect } from '../../types';
export function createEdgeTypes(edgeTypes: EdgeTypesType): EdgeTypesType {
const standardTypes: EdgeTypesType = {
@@ -59,7 +59,7 @@ export function getHandlePosition(position: Position, nodeRect: Rect, handle: an
}
}
export function getHandle(bounds: HandleElement[], handleId: ElementId | null): HandleElement | null {
export function getHandle(bounds: HandleElement[], handleId: string | null): HandleElement | null {
if (!bounds) {
return null;
}

View File

@@ -85,7 +85,7 @@ const NodeRenderer = (props: NodeRendererProps) => {
isHidden={node.isHidden}
xPos={internals?.positionAbsolute?.x || 0}
yPos={internals?.positionAbsolute?.y || 0}
dragging={node.dragging}
dragging={!!node.dragging}
isInitialized={isInitialized}
snapGrid={snapGrid}
snapToGrid={snapToGrid}

View File

@@ -4,28 +4,20 @@ import DefaultNode from '../../components/Nodes/DefaultNode';
import InputNode from '../../components/Nodes/InputNode';
import OutputNode from '../../components/Nodes/OutputNode';
import wrapNode from '../../components/Nodes/wrapNode';
import { NodeTypesType, NodeComponentProps } from '../../types';
import { NodeTypesType, NodeProps } from '../../types';
export function createNodeTypes(nodeTypes: NodeTypesType): NodeTypesType {
const standardTypes: NodeTypesType = {
input: wrapNode((nodeTypes.input || InputNode) as ComponentType<
NodeComponentProps
>),
default: wrapNode((nodeTypes.default || DefaultNode) as ComponentType<
NodeComponentProps
>),
output: wrapNode((nodeTypes.output || OutputNode) as ComponentType<
NodeComponentProps
>),
input: wrapNode((nodeTypes.input || InputNode) as ComponentType<NodeProps>),
default: wrapNode((nodeTypes.default || DefaultNode) as ComponentType<NodeProps>),
output: wrapNode((nodeTypes.output || OutputNode) as ComponentType<NodeProps>),
};
const wrappedTypes = {} as NodeTypesType;
const specialTypes: NodeTypesType = Object.keys(nodeTypes)
.filter(k => !['input', 'default', 'output'].includes(k))
.filter((k) => !['input', 'default', 'output'].includes(k))
.reduce((res, key) => {
res[key] = wrapNode((nodeTypes[key] || DefaultNode) as ComponentType<
NodeComponentProps
>);
res[key] = wrapNode((nodeTypes[key] || DefaultNode) as ComponentType<NodeProps>);
return res;
}, wrappedTypes);

View File

@@ -22,17 +22,17 @@ import {
OnSelectionChangeFunc,
NodeTypesType,
EdgeTypesType,
OnLoadFunc,
OnLoad,
Node,
Edge,
ConnectionMode,
ConnectionLineType,
ConnectionLineComponent,
FlowTransform,
OnConnectStartFunc,
OnConnectStopFunc,
OnConnectEndFunc,
OnConnectFunc,
OnConnectStart,
OnConnectStop,
OnConnectEnd,
OnConnect,
CoordinateExtent,
KeyCode,
PanOnScrollMode,
@@ -72,11 +72,11 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void;
onNodeDrag?: (event: ReactMouseEvent, node: Node) => void;
onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void;
onConnect?: OnConnectFunc;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: OnConnectStopFunc;
onConnectEnd?: OnConnectEndFunc;
onLoad?: OnLoadFunc;
onConnect?: OnConnect;
onConnectStart?: OnConnectStart;
onConnectStop?: OnConnectStop;
onConnectEnd?: OnConnectEnd;
onLoad?: OnLoad;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
onMoveEnd?: (flowTransform?: FlowTransform) => void;

View File

@@ -1,8 +1,6 @@
import { createContext } from 'react';
import { ElementId } from '../types';
type ContextProps = ElementId | null;
type ContextProps = string | null;
export const NodeIdContext = createContext<Partial<ContextProps>>(null);
export const Provider = NodeIdContext.Provider;

View File

@@ -3,9 +3,9 @@ import { useEffect, useRef } from 'react';
import { pointToRendererPoint } from '../utils/graph';
import { useStoreApi } from '../store';
import useZoomPanHelper from '../hooks/useZoomPanHelper';
import { OnLoadFunc, XYPosition, Node, Edge, FlowExportObject } from '../types';
import { OnLoad, XYPosition, Node, Edge, FlowExportObject } from '../types';
function useOnLoadHandler(onLoad: OnLoadFunc<any> | undefined) {
function useOnLoadHandler(onLoad: OnLoad<any> | undefined) {
const isInitialized = useRef<boolean>(false);
const store = useStoreApi();
const { zoomIn, zoomOut, zoomTo, transform: setTransform, fitView, initialized } = useZoomPanHelper();

View File

@@ -1,14 +1,14 @@
import { useCallback } from 'react';
import { useStore } from '../store';
import { ElementId, UpdateNodeInternals, ReactFlowState } from '../types';
import { UpdateNodeInternals, ReactFlowState } from '../types';
const updateNodeDimsSelector = (state: ReactFlowState) => state.updateNodeDimensions;
function useUpdateNodeInternals(): UpdateNodeInternals {
const updateNodeDimensions = useStore(updateNodeDimsSelector);
return useCallback<UpdateNodeInternals>((id: ElementId) => {
return useCallback<UpdateNodeInternals>((id: string) => {
const nodeElement = document.querySelector(`.react-flow__node[data-id="${id}"]`) as HTMLDivElement;
if (nodeElement) {

View File

@@ -4,7 +4,7 @@ import shallow from 'zustand/shallow';
import { useStoreApi, useStore } from '../store';
import { getRectOfNodes, pointToRendererPoint, getTransformForBounds } from '../utils/graph';
import { FitViewParams, FlowTransform, ZoomPanHelperFunctions, Rect, XYPosition, ReactFlowState } from '../types';
import { FitViewParams, FlowTransform, ZoomPanHelperFunctions, ReactFlowState, Rect, XYPosition } from '../types';
const DEFAULT_PADDING = 0.1;

View File

@@ -9,15 +9,12 @@ import {
Edge,
NodeDimensionUpdate,
NodeDiffUpdate,
XYPosition,
InitD3ZoomPayload,
CoordinateExtent,
Transform,
Dimensions,
OnConnectFunc,
OnConnectStartFunc,
OnConnectStopFunc,
OnConnectEndFunc,
OnConnect,
OnConnectStart,
OnConnectStop,
OnConnectEnd,
SetConnectionId,
SnapGrid,
NodeChange,
@@ -25,18 +22,20 @@ import {
OnEdgesChange,
EdgeChange,
NodeDimensionChange,
Transform,
Dimensions,
XYPosition,
} from '../types';
import { isNode, isEdge, getRectOfNodes, getNodesInside, getConnectedEdges } from '../utils/graph';
import { getHandleBounds } from '../components/Nodes/utils';
import { createNodeInternals } from './utils';
import { createNodeInternals, createNodeOrEdgeSelectionChange } from './utils';
const { Provider, useStore, useStoreApi } = createContext<ReactFlowState>();
const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge) => ({
id: item.id,
type: 'select',
selected,
});
const infiniteExtent: CoordinateExtent = [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
];
const createStore = () =>
create<ReactFlowState>((set, get) => ({
@@ -47,27 +46,16 @@ const createStore = () =>
edges: [],
onNodesChange: null,
onEdgesChange: null,
selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 },
d3Zoom: null,
d3Selection: null,
d3ZoomHandler: undefined,
minZoom: 0.5,
maxZoom: 2,
translateExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
nodeExtent: [
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
[Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
],
translateExtent: infiniteExtent,
nodeExtent: infiniteExtent,
nodesSelectionActive: false,
selectionActive: false,
userSelectionRect: {
startX: 0,
startY: 0,
@@ -345,10 +333,10 @@ const createStore = () =>
unsetNodesSelection: () => set({ nodesSelectionActive: false }),
updateTransform: (transform: Transform) => set({ transform }),
updateSize: (size: Dimensions) => set({ width: size.width || 500, height: size.height || 500 }),
setOnConnect: (onConnect: OnConnectFunc) => set({ onConnect }),
setOnConnectStart: (onConnectStart: OnConnectStartFunc) => set({ onConnectStart }),
setOnConnectStop: (onConnectStop: OnConnectStopFunc) => set({ onConnectStop }),
setOnConnectEnd: (onConnectEnd: OnConnectEndFunc) => set({ onConnectEnd }),
setOnConnect: (onConnect: OnConnect) => set({ onConnect }),
setOnConnectStart: (onConnectStart: OnConnectStart) => set({ onConnectStart }),
setOnConnectStop: (onConnectStop: OnConnectStop) => set({ onConnectStop }),
setOnConnectEnd: (onConnectEnd: OnConnectEnd) => set({ onConnectEnd }),
setConnectionPosition: (connectionPosition: XYPosition) => set({ connectionPosition }),
setConnectionNodeId: (params: SetConnectionId) => set({ ...params }),
setSnapToGrid: (snapToGrid: boolean) => set({ snapToGrid }),

View File

@@ -1,7 +1,6 @@
import { ElementId, Node, NodeInternals, NodeInternalsItem, XYPosition } from '../types';
import { Node, Edge, NodeInternals, NodeInternalsItem, XYZPosition } from '../types';
type XYZPosition = XYPosition & { z: number };
type ParentNodes = Record<ElementId, boolean>;
type ParentNodes = Record<string, boolean>;
function calculateXYZPosition(
node: NodeInternalsItem,
@@ -33,7 +32,7 @@ function calculateXYZPosition(
});
}
export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals): NodeInternals {
const nextNodeInternals = new Map<ElementId, NodeInternalsItem>();
const nextNodeInternals = new Map<string, NodeInternalsItem>();
const parentNodes: ParentNodes = {};
nodes.forEach((node) => {
@@ -86,3 +85,9 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals)
return nextNodeInternals;
}
export const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge) => ({
id: item.id,
type: 'select',
selected,
});

28
src/types/changes.ts Normal file
View File

@@ -0,0 +1,28 @@
import { XYPosition, Dimensions } from './utils';
import { NodeHandleBounds } from './nodes';
export type NodeDimensionChange = {
id: string;
type: 'dimensions';
dimensions?: Dimensions;
position?: XYPosition;
handleBounds?: NodeHandleBounds;
dragging?: boolean;
};
export type NodeSelectionChange = {
id: string;
type: 'select';
selected: boolean;
};
export type NodeRemoveChange = {
id: string;
type: 'remove';
};
export type NodeChange = NodeDimensionChange | NodeSelectionChange | NodeRemoveChange;
export type EdgeSelectionChange = NodeSelectionChange;
export type EdgeRemoveChange = NodeRemoveChange;
export type EdgeChange = EdgeSelectionChange | EdgeRemoveChange;

158
src/types/edges.ts Normal file
View File

@@ -0,0 +1,158 @@
import { CSSProperties, ReactNode, HTMLAttributes } from 'react';
import { Position } from './utils';
import { OnConnect, Connection } from './general';
import { HandleElement } from './handles';
import { Node } from './nodes';
// interface for the user edge items
export interface Edge<T = any> {
id: string;
type?: string;
source: string;
target: string;
sourceHandle?: string | null;
targetHandle?: string | null;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
animated?: boolean;
isHidden?: boolean;
data?: T;
className?: string;
sourceNode?: Node;
targetNode?: Node;
selected?: boolean;
markerStart?: EdgeMarkerType;
markerEnd?: EdgeMarkerType;
}
// props that get passed to a custom edge
export interface EdgeProps<T = any> {
id: string;
source: string;
target: string;
sourceX: number;
sourceY: number;
targetX: number;
targetY: number;
selected?: boolean;
animated?: boolean;
sourcePosition: Position;
targetPosition: Position;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
data?: T;
sourceHandleId?: string | null;
targetHandleId?: string | null;
markerStart?: string;
markerEnd?: string;
}
export type EdgeMouseHandler = (event: React.MouseEvent, edge: Edge) => void;
export interface WrapEdgeProps<T = any> {
id: string;
className?: string;
type: string;
data?: T;
onClick?: EdgeMouseHandler;
onEdgeDoubleClick?: EdgeMouseHandler;
selected: boolean;
animated?: boolean;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
source: string;
target: string;
sourceHandleId: string | null;
targetHandleId: string | null;
sourceX: number;
sourceY: number;
targetX: number;
targetY: number;
sourcePosition: Position;
targetPosition: Position;
elementsSelectable?: boolean;
isHidden?: boolean;
handleEdgeUpdate: boolean;
onConnectEdge: OnConnect;
onContextMenu?: EdgeMouseHandler;
onMouseEnter?: EdgeMouseHandler;
onMouseMove?: EdgeMouseHandler;
onMouseLeave?: EdgeMouseHandler;
edgeUpdaterRadius?: number;
onEdgeUpdateStart?: EdgeMouseHandler;
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge) => void;
markerStart?: EdgeMarkerType;
markerEnd?: EdgeMarkerType;
}
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
borderRadius?: number;
}
export interface EdgeTextProps extends HTMLAttributes<SVGElement> {
x: number;
y: number;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
}
export enum ConnectionLineType {
Bezier = 'default',
Straight = 'straight',
Step = 'step',
SmoothStep = 'smoothstep',
}
export type ConnectionLineComponentProps = {
sourceX: number;
sourceY: number;
sourcePosition?: Position;
targetX: number;
targetY: number;
targetPosition?: Position;
connectionLineStyle?: CSSProperties;
connectionLineType: ConnectionLineType;
sourceNode?: Node;
sourceHandle?: HandleElement;
};
export type ConnectionLineComponent = React.ComponentType<ConnectionLineComponentProps>;
export type OnEdgeUpdateFunc<T = any> = (oldEdge: Edge<T>, newConnection: Connection) => void;
export interface EdgeMarker {
type: ArrowHeadType;
color?: string;
width?: number;
height?: number;
units?: string;
orient?: string;
strokeWidth?: number;
}
export type EdgeMarkerType = string | EdgeMarker;
export enum ArrowHeadType {
Arrow = 'arrow',
ArrowClosed = 'arrowclosed',
}

217
src/types/general.ts Normal file
View File

@@ -0,0 +1,217 @@
import { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
import { Selection as D3Selection, ZoomBehavior } from 'd3';
import { XYPosition, Rect, Transform, CoordinateExtent, Dimensions } from './utils';
import { NodeChange, EdgeChange } from './changes';
import { Node, NodeInternals, NodeDimensionUpdate, NodeDiffUpdate } from './nodes';
import { Edge } from './edges';
import { HandleType } from './handles';
export type FlowElement<T = any> = Node<T> | Edge<T>;
export type Elements<T = any> = Array<FlowElement<T>>;
export type NodeTypesType = { [key: string]: ReactNode };
export type EdgeTypesType = NodeTypesType;
export type FitView = (fitViewOptions?: FitViewParams) => void;
export type Project = (position: XYPosition) => XYPosition;
export type ToObject<T = any> = () => FlowExportObject<T>;
export type OnNodesChange = (nodes: NodeChange[]) => void;
export type OnEdgesChange = (nodes: EdgeChange[]) => void;
export interface SelectionRect extends Rect {
startX: number;
startY: number;
draw: boolean;
}
export type OnLoadParams<T = any> = {
zoomIn: () => void;
zoomOut: () => void;
zoomTo: (zoomLevel: number) => void;
fitView: FitView;
project: Project;
getNodes: () => Node<T>[];
getEdges: () => Edge<T>[];
setTransform: (transform: FlowTransform) => void;
toObject: ToObject<T>;
};
export type OnLoad<T = any> = (params: OnLoadParams<T>) => void;
export interface Connection {
source: string | null;
target: string | null;
sourceHandle: string | null;
targetHandle: string | null;
}
export enum ConnectionMode {
Strict = 'strict',
Loose = 'loose',
}
export type FlowExportObject<T = any> = {
nodes: Node<T>[];
edges: Edge<T>[];
position: [number, number];
zoom: number;
};
export type OnConnect = (connection: Connection) => void;
export type FitViewParams = {
padding?: number;
includeHiddenNodes?: boolean;
minZoom?: number;
maxZoom?: number;
};
export type OnConnectStartParams = {
nodeId: string | null;
handleId: string | null;
handleType: HandleType | null;
};
export type OnConnectStart = (event: ReactMouseEvent, params: OnConnectStartParams) => void;
export type OnConnectStop = (event: MouseEvent) => void;
export type OnConnectEnd = (event: MouseEvent) => void;
export type SetConnectionId = {
connectionNodeId: string | null;
connectionHandleId: string | null;
connectionHandleType: HandleType | null;
};
export enum BackgroundVariant {
Lines = 'lines',
Dots = 'dots',
}
export type FlowTransform = {
x: number;
y: number;
zoom: number;
};
export type KeyCode = string | Array<string>;
export type SnapGrid = [number, number];
export enum PanOnScrollMode {
Free = 'free',
Vertical = 'vertical',
Horizontal = 'horizontal',
}
export interface ZoomPanHelperFunctions {
zoomIn: () => void;
zoomOut: () => void;
zoomTo: (zoomLevel: number) => void;
transform: (transform: FlowTransform) => void;
fitView: FitView;
setCenter: (x: number, y: number, zoom?: number) => void;
fitBounds: (bounds: Rect, padding?: number) => void;
project: (position: XYPosition) => XYPosition;
initialized: boolean;
}
export type InitD3ZoomPayload = {
d3Zoom: ZoomBehavior<Element, unknown>;
d3Selection: D3Selection<Element, unknown, null, undefined>;
d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined;
transform: Transform;
};
export interface ReactFlowState {
width: number;
height: number;
transform: Transform;
nodes: Node[];
nodeInternals: NodeInternals;
edges: Edge[];
selectedNodesBbox: Rect;
onNodesChange: OnNodesChange | null;
onEdgesChange: OnEdgesChange | null;
d3Zoom: ZoomBehavior<Element, unknown> | null;
d3Selection: D3Selection<Element, unknown, null, undefined> | null;
d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined;
minZoom: number;
maxZoom: number;
translateExtent: CoordinateExtent;
nodeExtent: CoordinateExtent;
nodesSelectionActive: boolean;
selectionActive: boolean;
userSelectionRect: SelectionRect;
connectionNodeId: string | null;
connectionHandleId: string | null;
connectionHandleType: HandleType | null;
connectionPosition: XYPosition;
connectionMode: ConnectionMode;
snapToGrid: boolean;
snapGrid: SnapGrid;
nodesDraggable: boolean;
nodesConnectable: boolean;
elementsSelectable: boolean;
multiSelectionActive: boolean;
reactFlowVersion: string;
setNodes: (nodes: Node[]) => void;
setEdges: (edges: Edge[], nodes: Node[]) => void;
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void;
updateNodePosition: (update: NodeDiffUpdate) => void;
setUserSelection: (mousePos: XYPosition) => void;
updateUserSelection: (mousePos: XYPosition) => void;
unsetUserSelection: () => void;
unsetNodesSelection: () => void;
resetSelectedElements: () => void;
unselectNodesAndEdges: () => void;
addSelectedElements: (elements: Elements) => void;
updateTransform: (transform: Transform) => void;
updateSize: (size: Dimensions) => void;
initD3Zoom: (payload: InitD3ZoomPayload) => void;
setMinZoom: (minZoom: number) => void;
setMaxZoom: (maxZoom: number) => void;
setTranslateExtent: (translateExtent: CoordinateExtent) => void;
setNodeExtent: (nodeExtent: CoordinateExtent) => void;
setOnConnect: (onConnectFunction: OnConnect) => void;
setOnConnectStart: (onConnectFunction: OnConnectStart) => void;
setOnConnectStop: (onConnectFunction: OnConnectStop) => void;
setOnConnectEnd: (onConnectFunction: OnConnectEnd) => void;
setConnectionPosition: (connectionPosition: XYPosition) => void;
setConnectionNodeId: (payload: SetConnectionId) => void;
setSnapToGrid: (snapToGrid: boolean) => void;
setSnapGrid: (snapGrid: SnapGrid) => void;
setInteractive: (isInteractive: boolean) => void;
setNodesDraggable: (nodesDraggable: boolean) => void;
setNodesConnectable: (nodesConnectable: boolean) => void;
setElementsSelectable: (elementsSelectable: boolean) => void;
setMultiSelectionActive: (multiSelectionActive: boolean) => void;
setConnectionMode: (connectionMode: ConnectionMode) => void;
setOnNodesChange: (onNodesChange: OnNodesChange) => void;
setOnEdgesChange: (onEdgesChange: OnEdgesChange) => void;
onConnect?: OnConnect;
onConnectStart?: OnConnectStart;
onConnectStop?: OnConnectStop;
onConnectEnd?: OnConnectEnd;
}
export type UpdateNodeInternals = (nodeId: string) => void;
export type OnSelectionChangeFunc = (params: { nodes: Node[]; edges: Edge[] }) => void;

18
src/types/handles.ts Normal file
View File

@@ -0,0 +1,18 @@
import { XYPosition, Position, Dimensions } from './utils';
import { OnConnect, Connection } from './general';
export type HandleType = 'source' | 'target';
export interface HandleElement extends XYPosition, Dimensions {
id?: string | null;
position: Position;
}
export interface HandleProps {
type: HandleType;
position: Position;
isConnectable?: boolean;
onConnect?: OnConnect;
isValidConnection?: (connection: Connection) => boolean;
id?: string;
}

View File

@@ -1,565 +1,6 @@
import React, { CSSProperties, MouseEvent as ReactMouseEvent, HTMLAttributes, ReactNode } from 'react';
import { Selection as D3Selection, ZoomBehavior } from 'd3';
export type ElementId = string;
export type FlowElement<T = any> = Node<T> | Edge<T>;
export type Elements<T = any> = Array<FlowElement<T>>;
export type Transform = [number, number, number];
export type NodeDimensionChange = {
id: string;
type: 'dimensions';
dimensions?: Dimensions;
position?: XYPosition;
handleBounds?: NodeHandleBounds;
dragging?: boolean;
};
export type NodeSelectionChange = {
id: string;
type: 'select';
selected: boolean;
};
export type NodeRemoveChange = {
id: string;
type: 'remove';
};
export type NodeChange = NodeDimensionChange | NodeSelectionChange | NodeRemoveChange;
export type EdgeSelectionChange = NodeSelectionChange;
export type EdgeRemoveChange = NodeRemoveChange;
export type EdgeChange = EdgeSelectionChange | EdgeRemoveChange;
export enum Position {
Left = 'left',
Top = 'top',
Right = 'right',
Bottom = 'bottom',
}
export interface XYPosition {
x: number;
y: number;
}
export interface Dimensions {
width: number;
height: number;
}
export interface Rect extends Dimensions, XYPosition {}
export interface Box extends XYPosition {
x2: number;
y2: number;
}
export type SnapGrid = [number, number];
export type NodeHandleBounds = {
source: HandleElement[] | null;
target: HandleElement[] | null;
};
export interface Node<T = any> {
id: ElementId;
position: XYPosition;
type?: string;
data?: T;
style?: CSSProperties;
className?: string;
targetPosition?: Position;
sourcePosition?: Position;
isHidden?: boolean;
selected?: boolean;
dragging?: boolean;
draggable?: boolean;
selectable?: boolean;
connectable?: boolean;
dragHandle?: string;
width?: number | null;
height?: number | null;
parentNode?: ElementId;
zIndex?: number;
extent?: 'parent' | CoordinateExtent;
}
export enum ArrowHeadType {
Arrow = 'arrow',
ArrowClosed = 'arrowclosed',
}
export interface EdgeMarker {
type: ArrowHeadType;
color?: string;
width?: number;
height?: number;
units?: string;
orient?: string;
strokeWidth?: number;
}
export type EdgeMarkerType = string | EdgeMarker;
export interface Edge<T = any> {
id: ElementId;
type?: string;
source: ElementId;
target: ElementId;
sourceHandle?: ElementId | null;
targetHandle?: ElementId | null;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
animated?: boolean;
isHidden?: boolean;
data?: T;
className?: string;
sourceNode?: Node;
targetNode?: Node;
selected?: boolean;
markerStart?: EdgeMarkerType;
markerEnd?: EdgeMarkerType;
}
export enum BackgroundVariant {
Lines = 'lines',
Dots = 'dots',
}
export type HandleType = 'source' | 'target';
export type NodeTypesType = { [key: string]: ReactNode };
export type EdgeTypesType = NodeTypesType;
export interface SelectionRect extends Rect {
startX: number;
startY: number;
draw: boolean;
}
export interface WrapEdgeProps<T = any> {
id: ElementId;
className?: string;
type: string;
data?: T;
onClick?: (event: React.MouseEvent, edge: Edge) => void;
onEdgeDoubleClick?: (event: React.MouseEvent, edge: Edge) => void;
selected: boolean;
animated?: boolean;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
source: ElementId;
target: ElementId;
sourceHandleId: ElementId | null;
targetHandleId: ElementId | null;
sourceX: number;
sourceY: number;
targetX: number;
targetY: number;
sourcePosition: Position;
targetPosition: Position;
elementsSelectable?: boolean;
isHidden?: boolean;
handleEdgeUpdate: boolean;
onConnectEdge: OnConnectFunc;
onContextMenu?: (event: React.MouseEvent, edge: Edge) => void;
onMouseEnter?: (event: React.MouseEvent, edge: Edge) => void;
onMouseMove?: (event: React.MouseEvent, edge: Edge) => void;
onMouseLeave?: (event: React.MouseEvent, edge: Edge) => void;
edgeUpdaterRadius?: number;
onEdgeUpdateStart?: (event: React.MouseEvent, edge: Edge) => void;
onEdgeUpdateEnd?: (event: MouseEvent, edge: Edge) => void;
markerStart?: EdgeMarkerType;
markerEnd?: EdgeMarkerType;
}
export interface EdgeProps<T = any> {
id: ElementId;
source: ElementId;
target: ElementId;
sourceX: number;
sourceY: number;
targetX: number;
targetY: number;
selected?: boolean;
animated?: boolean;
sourcePosition: Position;
targetPosition: Position;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
style?: CSSProperties;
data?: T;
sourceHandleId?: ElementId | null;
targetHandleId?: ElementId | null;
markerStart?: string;
markerEnd?: string;
}
export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
borderRadius?: number;
}
export interface EdgeTextProps extends HTMLAttributes<SVGElement> {
x: number;
y: number;
label?: string | ReactNode;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
labelBgPadding?: [number, number];
labelBgBorderRadius?: number;
}
export interface NodeProps<T = any> {
id: ElementId;
type: string;
data: T;
selected: boolean;
isConnectable: boolean;
xPos?: number;
yPos?: number;
targetPosition?: Position;
sourcePosition?: Position;
dragging?: boolean;
dragHandle?: string;
zIndex?: number;
}
export interface NodeComponentProps<T = any> {
id: ElementId;
type: string;
data: T;
selected?: boolean;
isConnectable: boolean;
transform?: Transform;
xPos?: number;
yPos?: number;
targetPosition?: Position;
sourcePosition?: Position;
onClick?: (node: Node) => void;
onNodeDoubleClick?: (node: Node) => void;
onMouseEnter?: (node: Node) => void;
onMouseMove?: (node: Node) => void;
onMouseLeave?: (node: Node) => void;
onContextMenu?: (node: Node) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDrag?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
style?: CSSProperties;
dragging?: boolean;
dragHandle?: string;
zIndex?: number;
}
export interface WrapNodeProps<T = any> {
id: ElementId;
type: string;
data: T;
selected: boolean;
scale: number;
xPos: number;
yPos: number;
width?: number | null;
height?: number | null;
isSelectable: boolean;
isDraggable: boolean;
isConnectable: boolean;
selectNodesOnDrag: boolean;
onClick?: (event: ReactMouseEvent, node: Node) => void;
onNodeDoubleClick?: (event: ReactMouseEvent, node: Node) => void;
onMouseEnter?: (event: ReactMouseEvent, node: Node) => void;
onMouseMove?: (event: ReactMouseEvent, node: Node) => void;
onMouseLeave?: (event: ReactMouseEvent, node: Node) => void;
onContextMenu?: (event: ReactMouseEvent, node: Node) => void;
onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void;
onNodeDrag?: (event: ReactMouseEvent, node: Node) => void;
onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void;
style?: CSSProperties;
className?: string;
sourcePosition?: Position;
targetPosition?: Position;
isHidden?: boolean;
isInitialized?: boolean;
snapToGrid?: boolean;
snapGrid?: SnapGrid;
dragging?: boolean;
resizeObserver: ResizeObserver | null;
dragHandle?: string;
zIndex: number;
isParent: boolean;
}
export type FitViewParams = {
padding?: number;
includeHiddenNodes?: boolean;
minZoom?: number;
maxZoom?: number;
};
export type FlowExportObject<T = any> = {
nodes: Node<T>[];
edges: Edge<T>[];
position: [number, number];
zoom: number;
};
export type FitViewFunc = (fitViewOptions?: FitViewParams) => void;
export type ProjectFunc = (position: XYPosition) => XYPosition;
export type ToObjectFunc<T = any> = () => FlowExportObject<T>;
export type OnLoadParams<T = any> = {
zoomIn: () => void;
zoomOut: () => void;
zoomTo: (zoomLevel: number) => void;
fitView: FitViewFunc;
project: ProjectFunc;
getNodes: () => Node<T>[];
getEdges: () => Edge<T>[];
setTransform: (transform: FlowTransform) => void;
toObject: ToObjectFunc<T>;
};
export type OnLoadFunc<T = any> = (params: OnLoadParams<T>) => void;
export interface Connection {
source: ElementId | null;
target: ElementId | null;
sourceHandle: ElementId | null;
targetHandle: ElementId | null;
}
export enum ConnectionMode {
Strict = 'strict',
Loose = 'loose',
}
export enum ConnectionLineType {
Bezier = 'default',
Straight = 'straight',
Step = 'step',
SmoothStep = 'smoothstep',
}
export type ConnectionLineComponentProps = {
sourceX: number;
sourceY: number;
sourcePosition?: Position;
targetX: number;
targetY: number;
targetPosition?: Position;
connectionLineStyle?: CSSProperties;
connectionLineType: ConnectionLineType;
sourceNode?: Node;
sourceHandle?: HandleElement;
};
export type ConnectionLineComponent = React.ComponentType<ConnectionLineComponentProps>;
export type OnConnectFunc = (connection: Connection) => void;
export type OnConnectStartParams = {
nodeId: ElementId | null;
handleId: ElementId | null;
handleType: HandleType | null;
};
export type OnConnectStartFunc = (event: ReactMouseEvent, params: OnConnectStartParams) => void;
export type OnConnectStopFunc = (event: MouseEvent) => void;
export type OnConnectEndFunc = (event: MouseEvent) => void;
export type SetConnectionId = {
connectionNodeId: ElementId | null;
connectionHandleId: ElementId | null;
connectionHandleType: HandleType | null;
};
export interface HandleElement extends XYPosition, Dimensions {
id?: ElementId | null;
position: Position;
}
export interface HandleProps {
type: HandleType;
position: Position;
isConnectable?: boolean;
onConnect?: OnConnectFunc;
isValidConnection?: (connection: Connection) => boolean;
id?: ElementId;
}
export type NodePosUpdate = {
id: ElementId;
pos: XYPosition;
};
export type NodeDiffUpdate = {
id?: ElementId;
diff?: XYPosition;
dragging?: boolean;
};
export type FlowTransform = {
x: number;
y: number;
zoom: number;
};
export type CoordinateExtent = [[number, number], [number, number]];
export type KeyCode = string | Array<string>;
export enum PanOnScrollMode {
Free = 'free',
Vertical = 'vertical',
Horizontal = 'horizontal',
}
export interface ZoomPanHelperFunctions {
zoomIn: () => void;
zoomOut: () => void;
zoomTo: (zoomLevel: number) => void;
transform: (transform: FlowTransform) => void;
fitView: FitViewFunc;
setCenter: (x: number, y: number, zoom?: number) => void;
fitBounds: (bounds: Rect, padding?: number) => void;
project: (position: XYPosition) => XYPosition;
initialized: boolean;
}
export type OnEdgeUpdateFunc<T = any> = (oldEdge: Edge<T>, newConnection: Connection) => void;
export type NodeDimensionUpdate = {
id: ElementId;
nodeElement: HTMLDivElement;
forceUpdate?: boolean;
};
export type InitD3ZoomPayload = {
d3Zoom: ZoomBehavior<Element, unknown>;
d3Selection: D3Selection<Element, unknown, null, undefined>;
d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined;
transform: Transform;
};
export type OnNodesChange = (nodes: NodeChange[]) => void;
export type OnEdgesChange = (nodes: EdgeChange[]) => void;
export type NodeInternalsItem = {
id?: string;
width?: number | null;
height?: number | null;
parentNode?: ElementId;
position?: XYPosition;
positionAbsolute?: XYPosition;
handleBounds?: NodeHandleBounds;
z?: number;
isParent?: boolean;
};
export type NodeInternals = Map<ElementId, NodeInternalsItem>;
export interface ReactFlowState {
width: number;
height: number;
transform: Transform;
nodes: Node[];
nodeInternals: NodeInternals;
edges: Edge[];
selectedNodesBbox: Rect;
onNodesChange: OnNodesChange | null;
onEdgesChange: OnEdgesChange | null;
d3Zoom: ZoomBehavior<Element, unknown> | null;
d3Selection: D3Selection<Element, unknown, null, undefined> | null;
d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined;
minZoom: number;
maxZoom: number;
translateExtent: CoordinateExtent;
nodeExtent: CoordinateExtent;
nodesSelectionActive: boolean;
selectionActive: boolean;
userSelectionRect: SelectionRect;
connectionNodeId: ElementId | null;
connectionHandleId: ElementId | null;
connectionHandleType: HandleType | null;
connectionPosition: XYPosition;
connectionMode: ConnectionMode;
snapToGrid: boolean;
snapGrid: SnapGrid;
nodesDraggable: boolean;
nodesConnectable: boolean;
elementsSelectable: boolean;
multiSelectionActive: boolean;
reactFlowVersion: string;
setNodes: (nodes: Node[]) => void;
setEdges: (edges: Edge[], nodes: Node[]) => void;
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void;
updateNodePosition: (update: NodeDiffUpdate) => void;
setUserSelection: (mousePos: XYPosition) => void;
updateUserSelection: (mousePos: XYPosition) => void;
unsetUserSelection: () => void;
unsetNodesSelection: () => void;
resetSelectedElements: () => void;
unselectNodesAndEdges: () => void;
addSelectedElements: (elements: Elements) => void;
updateTransform: (transform: Transform) => void;
updateSize: (size: Dimensions) => void;
initD3Zoom: (payload: InitD3ZoomPayload) => void;
setMinZoom: (minZoom: number) => void;
setMaxZoom: (maxZoom: number) => void;
setTranslateExtent: (translateExtent: CoordinateExtent) => void;
setNodeExtent: (nodeExtent: CoordinateExtent) => void;
setOnConnect: (onConnectFunction: OnConnectFunc) => void;
setOnConnectStart: (onConnectFunction: OnConnectStartFunc) => void;
setOnConnectStop: (onConnectFunction: OnConnectStopFunc) => void;
setOnConnectEnd: (onConnectFunction: OnConnectEndFunc) => void;
setConnectionPosition: (connectionPosition: XYPosition) => void;
setConnectionNodeId: (payload: SetConnectionId) => void;
setSnapToGrid: (snapToGrid: boolean) => void;
setSnapGrid: (snapGrid: SnapGrid) => void;
setInteractive: (isInteractive: boolean) => void;
setNodesDraggable: (nodesDraggable: boolean) => void;
setNodesConnectable: (nodesConnectable: boolean) => void;
setElementsSelectable: (elementsSelectable: boolean) => void;
setMultiSelectionActive: (multiSelectionActive: boolean) => void;
setConnectionMode: (connectionMode: ConnectionMode) => void;
setOnNodesChange: (onNodesChange: OnNodesChange) => void;
setOnEdgesChange: (onEdgesChange: OnEdgesChange) => void;
onConnect?: OnConnectFunc;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: OnConnectStopFunc;
onConnectEnd?: OnConnectEndFunc;
}
export type UpdateNodeInternals = (nodeId: ElementId) => void;
export type OnSelectionChangeFunc = (params: { nodes: Node[]; edges: Edge[] }) => void;
export type NodeRendererNode = {
childNodes?: NodeRendererNode[];
node: Node;
};
export * from './general';
export * from './nodes';
export * from './edges';
export * from './handles';
export * from './changes';
export * from './utils';

116
src/types/nodes.ts Normal file
View File

@@ -0,0 +1,116 @@
import { CSSProperties, MouseEvent as ReactMouseEvent } from 'react';
import { SnapGrid } from './general';
import { XYPosition, Position, CoordinateExtent } from './utils';
import { HandleElement } from './handles';
// interface for the user node items
export interface Node<T = any> {
id: string;
position: XYPosition;
type?: string;
data?: T;
style?: CSSProperties;
className?: string;
targetPosition?: Position;
sourcePosition?: Position;
isHidden?: boolean;
selected?: boolean;
dragging?: boolean;
draggable?: boolean;
selectable?: boolean;
connectable?: boolean;
dragHandle?: string;
width?: number | null;
height?: number | null;
parentNode?: string;
zIndex?: number;
extent?: 'parent' | CoordinateExtent;
}
// props that get passed to a custom node
export interface NodeProps<T = any> {
id: string;
type: string;
data: T;
selected: boolean;
isConnectable: boolean;
xPos: number;
yPos: number;
dragging: boolean;
zIndex: number;
targetPosition?: Position;
sourcePosition?: Position;
dragHandle?: string;
}
export type NodeMouseHandler = (event: ReactMouseEvent, node: Node) => void;
export interface WrapNodeProps<T = any> {
id: string;
type: string;
data: T;
selected: boolean;
isConnectable: boolean;
scale: number;
xPos: number;
yPos: number;
width?: number | null;
height?: number | null;
isSelectable: boolean;
isDraggable: boolean;
selectNodesOnDrag: boolean;
onClick?: NodeMouseHandler;
onNodeDoubleClick?: NodeMouseHandler;
onMouseEnter?: NodeMouseHandler;
onMouseMove?: NodeMouseHandler;
onMouseLeave?: NodeMouseHandler;
onContextMenu?: NodeMouseHandler;
onNodeDragStart?: NodeMouseHandler;
onNodeDrag?: NodeMouseHandler;
onNodeDragStop?: NodeMouseHandler;
style?: CSSProperties;
className?: string;
sourcePosition?: Position;
targetPosition?: Position;
isHidden?: boolean;
isInitialized?: boolean;
snapToGrid?: boolean;
snapGrid?: SnapGrid;
dragging: boolean;
resizeObserver: ResizeObserver | null;
dragHandle?: string;
zIndex: number;
isParent: boolean;
}
export type NodeHandleBounds = {
source: HandleElement[] | null;
target: HandleElement[] | null;
};
export type NodeDiffUpdate = {
id?: string;
diff?: XYPosition;
dragging?: boolean;
};
export type NodeDimensionUpdate = {
id: string;
nodeElement: HTMLDivElement;
forceUpdate?: boolean;
};
export type NodeInternalsItem = {
id?: string;
width?: number | null;
height?: number | null;
parentNode?: string;
position?: XYPosition;
positionAbsolute?: XYPosition;
handleBounds?: NodeHandleBounds;
z?: number;
isParent?: boolean;
};
export type NodeInternals = Map<string, NodeInternalsItem>;

29
src/types/utils.ts Normal file
View File

@@ -0,0 +1,29 @@
export enum Position {
Left = 'left',
Top = 'top',
Right = 'right',
Bottom = 'bottom',
}
export interface XYPosition {
x: number;
y: number;
}
export type XYZPosition = XYPosition & { z: number };
export interface Dimensions {
width: number;
height: number;
}
export interface Rect extends Dimensions, XYPosition {}
export interface Box extends XYPosition {
x2: number;
y2: number;
}
export type Transform = [number, number, number];
export type CoordinateExtent = [[number, number], [number, number]];

View File

@@ -1,6 +1,6 @@
import { boxToRect, clamp, getBoundsOfBoxes, rectToBox } from '../utils';
import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, Connection, EdgeMarkerType } from '../types';
import { Node, Edge, Elements, Connection, EdgeMarkerType, Transform, XYPosition, Rect } from '../types';
export const isEdge = (element: Node | Connection | Edge): element is Edge =>
'id' in element && 'source' in element && 'target' in element;
@@ -26,7 +26,7 @@ export const getIncomers = (node: Node, nodes: Node[], edges: Edge[]): Node[] =>
return nodes.filter((n) => incomersIds.includes(n.id));
};
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): ElementId =>
const getEdgeId = ({ source, sourceHandle, target, targetHandle }: Connection): string =>
`reactflow__edge-${source}${sourceHandle}-${target}${targetHandle}`;
export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {