Merge pull request #208 from wbkd/develop
Text option for edges, release handling
This commit is contained in:
+1
-1
@@ -4,4 +4,4 @@ node_modules
|
|||||||
examples/build
|
examples/build
|
||||||
cypress/videos
|
cypress/videos
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
stats.html
|
dist
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.DS_Store
|
||||||
|
.cache
|
||||||
|
.vscode
|
||||||
|
.dependabot
|
||||||
|
node_modules
|
||||||
|
examples
|
||||||
|
cypress
|
||||||
|
dist
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"git": {
|
||||||
|
"commitMessage": "chore: release v${version}"
|
||||||
|
},
|
||||||
|
"github": {
|
||||||
|
"release": true
|
||||||
|
},
|
||||||
|
"hooks": {
|
||||||
|
"before:init": ["npm test"],
|
||||||
|
"after:bump": "npm run build",
|
||||||
|
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -130,7 +130,7 @@ You can find an example of how to implement a custom node in the [custom node ex
|
|||||||
|
|
||||||
There are three [edge types](#edge-types--custom-edges) (`straight`, `default`, `step`) you can use. The default type is `default`. You can also create [custom edges](#edge-types--custom-edges).
|
There are three [edge types](#edge-types--custom-edges) (`straight`, `default`, `step`) you can use. The default type is `default`. You can also create [custom edges](#edge-types--custom-edges).
|
||||||
|
|
||||||
Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animated: true }`
|
Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animated: true, label: 'edge label' }`
|
||||||
|
|
||||||
### Props
|
### Props
|
||||||
|
|
||||||
@@ -139,7 +139,13 @@ Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animate
|
|||||||
- `target`: string (an id of a node) *(required)*
|
- `target`: string (an id of a node) *(required)*
|
||||||
- `type`: 'input' | 'output' | 'default' or a custom one you implemented
|
- `type`: 'input' | 'output' | 'default' or a custom one you implemented
|
||||||
- `animated`: boolean
|
- `animated`: boolean
|
||||||
- `style`: css properties
|
- `style`: css properties for the edge line path
|
||||||
|
- `label`: string
|
||||||
|
- `labelStyle`: css properties for the text
|
||||||
|
- `labelShowBg`: boolean - default: `true`
|
||||||
|
- `labelBgStyle`: css properties for the text background
|
||||||
|
|
||||||
|
You can find an example with lots of different edges in the [edges example](https://react-flow.netlify.app/edges).
|
||||||
|
|
||||||
### Edge Types / Custom Edges
|
### Edge Types / Custom Edges
|
||||||
|
|
||||||
|
|||||||
Vendored
-9518
File diff suppressed because it is too large
Load Diff
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-9532
File diff suppressed because it is too large
Load Diff
Vendored
-1
File diff suppressed because one or more lines are too long
-10
@@ -1,10 +0,0 @@
|
|||||||
import React, { HTMLAttributes } from 'react';
|
|
||||||
import { GridType } from '../../types';
|
|
||||||
interface GridProps extends HTMLAttributes<SVGElement> {
|
|
||||||
backgroundType?: GridType;
|
|
||||||
gap?: number;
|
|
||||||
color?: string;
|
|
||||||
size?: number;
|
|
||||||
}
|
|
||||||
declare const Grid: React.MemoExoticComponent<({ gap, color, size, style, className, backgroundType, }: GridProps) => JSX.Element>;
|
|
||||||
export default Grid;
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
import { SVGAttributes } from 'react';
|
|
||||||
import { ElementId, Node, Transform } from '../../types';
|
|
||||||
interface ConnectionLineProps {
|
|
||||||
connectionSourceId: ElementId;
|
|
||||||
connectionPositionX: number;
|
|
||||||
connectionPositionY: number;
|
|
||||||
connectionLineType?: string | null;
|
|
||||||
nodes: Node[];
|
|
||||||
transform: Transform;
|
|
||||||
isInteractive: boolean;
|
|
||||||
connectionLineStyle?: SVGAttributes<{}>;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
declare const _default: ({ connectionSourceId, connectionLineStyle, connectionPositionX, connectionPositionY, connectionLineType, nodes, className, transform, isInteractive, }: ConnectionLineProps) => JSX.Element | null;
|
|
||||||
export default _default;
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { EdgeBezierProps } from '../../types';
|
|
||||||
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style, }: EdgeBezierProps) => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { EdgeProps } from '../../types';
|
|
||||||
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: EdgeProps) => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { EdgeProps } from '../../types';
|
|
||||||
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: EdgeProps) => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { ElementId, Edge, EdgeCompProps } from '../../types';
|
|
||||||
interface EdgeWrapperProps {
|
|
||||||
id: ElementId;
|
|
||||||
source: ElementId;
|
|
||||||
target: ElementId;
|
|
||||||
type: any;
|
|
||||||
onClick: (edge: Edge) => void;
|
|
||||||
animated: boolean;
|
|
||||||
selected: boolean;
|
|
||||||
isInteractive: boolean;
|
|
||||||
}
|
|
||||||
declare const _default: (EdgeComponent: React.ComponentType<EdgeCompProps>) => React.MemoExoticComponent<({ id, source, target, type, animated, selected, onClick, isInteractive, ...rest }: EdgeWrapperProps) => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { HandleType, ElementId, Position, XYPosition, OnConnectFunc, Connection } from '../../types';
|
|
||||||
declare type ValidConnectionFunc = (connection: Connection) => boolean;
|
|
||||||
declare type SetSourceIdFunc = (nodeId: ElementId | null) => void;
|
|
||||||
interface BaseHandleProps {
|
|
||||||
type: HandleType;
|
|
||||||
nodeId: ElementId;
|
|
||||||
onConnect: OnConnectFunc;
|
|
||||||
position: Position;
|
|
||||||
setSourceId: SetSourceIdFunc;
|
|
||||||
setPosition: (pos: XYPosition) => void;
|
|
||||||
isValidConnection: ValidConnectionFunc;
|
|
||||||
id?: ElementId | boolean;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
declare const BaseHandle: React.MemoExoticComponent<({ type, nodeId, onConnect, position, setSourceId, setPosition, className, id, isValidConnection, ...rest }: BaseHandleProps) => JSX.Element>;
|
|
||||||
export default BaseHandle;
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { HandleType, Position, OnConnectFunc } from '../../types';
|
|
||||||
interface HandleProps {
|
|
||||||
type: HandleType;
|
|
||||||
position: Position;
|
|
||||||
onConnect?: OnConnectFunc;
|
|
||||||
isValidConnection?: () => boolean;
|
|
||||||
}
|
|
||||||
declare const Handle: React.MemoExoticComponent<({ onConnect, type, position, isValidConnection, ...rest }: HandleProps) => JSX.Element>;
|
|
||||||
export default Handle;
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
/// <reference types="react" />
|
|
||||||
import { NodeProps } from '../../types';
|
|
||||||
declare const _default: ({ data, targetPosition, sourcePosition, style }: NodeProps) => JSX.Element;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
/// <reference types="react" />
|
|
||||||
import { NodeProps } from '../../types';
|
|
||||||
declare const _default: ({ data, style, sourcePosition }: NodeProps) => JSX.Element;
|
|
||||||
export default _default;
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
/// <reference types="react" />
|
|
||||||
import { NodeProps } from '../../types';
|
|
||||||
declare const _default: ({ data, style, targetPosition }: NodeProps) => JSX.Element;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
import { HandleElement } from '../../types';
|
|
||||||
export declare const getHandleBounds: (selector: string, nodeElement: HTMLDivElement, parentBounds: ClientRect | DOMRect, k: number) => HandleElement[] | null;
|
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { NodeComponentProps, WrapNodeProps } from '../../types';
|
|
||||||
declare const _default: (NodeComponent: React.ComponentType<NodeComponentProps>) => React.MemoExoticComponent<({ id, type, data, transform, xPos, yPos, selected, onClick, onNodeDragStop, style, isInteractive, sourcePosition, targetPosition, }: WrapNodeProps) => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
-7
@@ -1,7 +0,0 @@
|
|||||||
/**
|
|
||||||
* The nodes selection rectangle gets displayed when a user
|
|
||||||
* made a selectio with on or several nodes
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
declare const _default: React.MemoExoticComponent<() => JSX.Element>;
|
|
||||||
export default _default;
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
/**
|
|
||||||
* The user selection rectangle gets displayed when a user drags the mouse while pressing shift
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
declare type UserSelectionProps = {
|
|
||||||
isInteractive: boolean;
|
|
||||||
};
|
|
||||||
declare const _default: React.MemoExoticComponent<({ isInteractive }: UserSelectionProps) => JSX.Element | null>;
|
|
||||||
export default _default;
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
import React, { SVGAttributes } from 'react';
|
|
||||||
interface EdgeRendererProps {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
edgeTypes: any;
|
|
||||||
connectionLineStyle?: SVGAttributes<{}>;
|
|
||||||
connectionLineType?: string;
|
|
||||||
onElementClick?: () => void;
|
|
||||||
}
|
|
||||||
declare const EdgeRenderer: React.MemoExoticComponent<(props: EdgeRendererProps) => JSX.Element | null>;
|
|
||||||
export default EdgeRenderer;
|
|
||||||
-2
@@ -1,2 +0,0 @@
|
|||||||
import { EdgeTypesType } from '../../types';
|
|
||||||
export declare function createEdgeTypes(edgeTypes: EdgeTypesType): EdgeTypesType;
|
|
||||||
Vendored
-27
@@ -1,27 +0,0 @@
|
|||||||
import React, { SVGAttributes } from 'react';
|
|
||||||
import { Elements, NodeTypesType, EdgeTypesType, GridType, OnLoadFunc } from '../../types';
|
|
||||||
export interface GraphViewProps {
|
|
||||||
elements: Elements;
|
|
||||||
onElementClick: () => void;
|
|
||||||
onElementsRemove: (elements: Elements) => void;
|
|
||||||
onNodeDragStop: () => void;
|
|
||||||
onConnect: () => void;
|
|
||||||
onLoad: OnLoadFunc;
|
|
||||||
onMove: () => void;
|
|
||||||
selectionKeyCode: number;
|
|
||||||
nodeTypes: NodeTypesType;
|
|
||||||
edgeTypes: EdgeTypesType;
|
|
||||||
connectionLineType: string;
|
|
||||||
connectionLineStyle: SVGAttributes<{}>;
|
|
||||||
deleteKeyCode: number;
|
|
||||||
showBackground: boolean;
|
|
||||||
backgroundGap: number;
|
|
||||||
backgroundColor: string;
|
|
||||||
backgroundType: GridType;
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
onlyRenderVisibleNodes: boolean;
|
|
||||||
isInteractive: boolean;
|
|
||||||
}
|
|
||||||
declare const GraphView: React.MemoExoticComponent<({ nodeTypes, edgeTypes, onMove, onLoad, onElementClick, onNodeDragStop, connectionLineType, connectionLineStyle, selectionKeyCode, onElementsRemove, deleteKeyCode, elements, showBackground, backgroundGap, backgroundColor, backgroundType, onConnect, snapToGrid, snapGrid, onlyRenderVisibleNodes, isInteractive, }: GraphViewProps) => JSX.Element>;
|
|
||||||
export default GraphView;
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { NodeTypesType } from '../../types';
|
|
||||||
interface NodeRendererProps {
|
|
||||||
nodeTypes: NodeTypesType;
|
|
||||||
onElementClick: () => void;
|
|
||||||
onNodeDragStop: () => void;
|
|
||||||
onlyRenderVisibleNodes?: boolean;
|
|
||||||
}
|
|
||||||
declare const NodeRenderer: React.MemoExoticComponent<({ onlyRenderVisibleNodes, ...props }: NodeRendererProps) => JSX.Element>;
|
|
||||||
export default NodeRenderer;
|
|
||||||
-2
@@ -1,2 +0,0 @@
|
|||||||
import { NodeTypesType } from '../../types';
|
|
||||||
export declare function createNodeTypes(nodeTypes: NodeTypesType): NodeTypesType;
|
|
||||||
Vendored
-61
@@ -1,61 +0,0 @@
|
|||||||
import React, { SVGAttributes, HTMLAttributes } from 'react';
|
|
||||||
import { Elements, NodeTypesType, EdgeTypesType, GridType, OnLoadFunc } from '../../types';
|
|
||||||
import '../../style.css';
|
|
||||||
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> {
|
|
||||||
elements: Elements;
|
|
||||||
onElementClick: () => void;
|
|
||||||
onElementsRemove: (elements: Elements) => void;
|
|
||||||
onNodeDragStop: () => void;
|
|
||||||
onConnect: () => void;
|
|
||||||
onLoad: OnLoadFunc;
|
|
||||||
onMove: () => void;
|
|
||||||
nodeTypes: NodeTypesType;
|
|
||||||
edgeTypes: EdgeTypesType;
|
|
||||||
connectionLineType: string;
|
|
||||||
connectionLineStyle: SVGAttributes<{}>;
|
|
||||||
deleteKeyCode: number;
|
|
||||||
selectionKeyCode: number;
|
|
||||||
showBackground: boolean;
|
|
||||||
backgroundGap: number;
|
|
||||||
backgroundColor: string;
|
|
||||||
backgroundType: GridType;
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
onlyRenderVisibleNodes: boolean;
|
|
||||||
isInteractive: boolean;
|
|
||||||
}
|
|
||||||
declare const ReactFlow: {
|
|
||||||
({ style, onElementClick, elements, children, nodeTypes, edgeTypes, onLoad, onMove, onElementsRemove, onConnect, onNodeDragStop, connectionLineType, connectionLineStyle, deleteKeyCode, selectionKeyCode, showBackground, backgroundGap, backgroundType, backgroundColor, snapToGrid, snapGrid, onlyRenderVisibleNodes, isInteractive, }: ReactFlowProps): JSX.Element;
|
|
||||||
displayName: string;
|
|
||||||
defaultProps: {
|
|
||||||
onElementClick: () => void;
|
|
||||||
onElementsRemove: () => void;
|
|
||||||
onNodeDragStop: () => void;
|
|
||||||
onConnect: () => void;
|
|
||||||
onLoad: () => void;
|
|
||||||
onMove: () => void;
|
|
||||||
nodeTypes: {
|
|
||||||
input: ({ data, style, sourcePosition }: import("../../types").NodeProps) => JSX.Element;
|
|
||||||
default: ({ data, targetPosition, sourcePosition, style }: import("../../types").NodeProps) => JSX.Element;
|
|
||||||
output: ({ data, style, targetPosition }: import("../../types").NodeProps) => JSX.Element;
|
|
||||||
};
|
|
||||||
edgeTypes: {
|
|
||||||
default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style, }: import("../../types").EdgeBezierProps) => JSX.Element>;
|
|
||||||
straight: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: import("../../types").EdgeProps) => JSX.Element>;
|
|
||||||
step: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: import("../../types").EdgeProps) => JSX.Element>;
|
|
||||||
};
|
|
||||||
connectionLineType: string;
|
|
||||||
connectionLineStyle: {};
|
|
||||||
deleteKeyCode: number;
|
|
||||||
selectionKeyCode: number;
|
|
||||||
backgroundColor: string;
|
|
||||||
backgroundGap: number;
|
|
||||||
showBackground: boolean;
|
|
||||||
backgroundType: GridType;
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: number[];
|
|
||||||
onlyRenderVisibleNodes: boolean;
|
|
||||||
isInteractive: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default ReactFlow;
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
/// <reference types="react" />
|
|
||||||
import { ElementId } from '../types';
|
|
||||||
declare type ContextProps = ElementId | null;
|
|
||||||
export declare const NodeIdContext: import("react").Context<ContextProps>;
|
|
||||||
export declare const Provider: import("react").Provider<ContextProps>;
|
|
||||||
export declare const Consumer: import("react").Consumer<ContextProps>;
|
|
||||||
export default NodeIdContext;
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
import { MutableRefObject } from 'react';
|
|
||||||
declare const _default: (zoomPane: MutableRefObject<Element | null>, onMove: () => void, shiftPressed: boolean) => void;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-3
@@ -1,3 +0,0 @@
|
|||||||
import { Elements } from '../types';
|
|
||||||
declare const useElementUpdater: (elements: Elements) => void;
|
|
||||||
export default useElementUpdater;
|
|
||||||
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
import { Elements } from '../types';
|
|
||||||
interface HookParams {
|
|
||||||
deleteKeyCode: number;
|
|
||||||
onElementsRemove: (elements: Elements) => void;
|
|
||||||
}
|
|
||||||
declare const _default: ({ deleteKeyCode, onElementsRemove }: HookParams) => void;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
declare const _default: (keyCode: number) => boolean;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
import ReactFlow from './container/ReactFlow';
|
|
||||||
export default ReactFlow;
|
|
||||||
export { default as Handle } from './components/Handle';
|
|
||||||
export { MiniMap, Controls } from './plugins';
|
|
||||||
export { isNode, isEdge, removeElements, addEdge, getOutgoers, } from './utils/graph';
|
|
||||||
Vendored
-5
@@ -1,5 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
interface ControlProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
||||||
}
|
|
||||||
declare const _default: ({ style, className }: ControlProps) => JSX.Element;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-10
@@ -1,10 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Node } from '../../types';
|
|
||||||
declare type StringFunc = (node: Node) => string;
|
|
||||||
interface MiniMapProps extends React.HTMLAttributes<SVGSVGElement> {
|
|
||||||
nodeColor: string | StringFunc;
|
|
||||||
nodeBorderRadius: number;
|
|
||||||
maskColor: string;
|
|
||||||
}
|
|
||||||
declare const _default: ({ style, className, nodeColor, nodeBorderRadius, maskColor, }: MiniMapProps) => JSX.Element;
|
|
||||||
export default _default;
|
|
||||||
Vendored
-2
@@ -1,2 +0,0 @@
|
|||||||
export { default as MiniMap } from './MiniMap';
|
|
||||||
export { default as Controls } from './Controls';
|
|
||||||
Vendored
-71
@@ -1,71 +0,0 @@
|
|||||||
import { StoreModel } from './index';
|
|
||||||
export declare const useStoreActions: <Result>(mapActions: (actions: import("easy-peasy").ActionMapper<{
|
|
||||||
selectedNodesBbox: import("../types").Rect;
|
|
||||||
d3Zoom: import("d3-zoom").ZoomBehavior<Element, unknown> | null;
|
|
||||||
d3Selection: import("d3-selection").Selection<Element, unknown, null, undefined> | null;
|
|
||||||
selection: import("../types").SelectionRect | null;
|
|
||||||
userSelectionRect: import("../types").SelectionRect;
|
|
||||||
connectionPosition: import("../types").XYPosition;
|
|
||||||
onConnect: import("../types").OnConnectFunc;
|
|
||||||
setOnConnect: import("easy-peasy").Action<StoreModel, import("../types").OnConnectFunc>;
|
|
||||||
setNodes: import("easy-peasy").Action<StoreModel, import("../types").Node[]>;
|
|
||||||
setEdges: import("easy-peasy").Action<StoreModel, import("../types").Edge[]>;
|
|
||||||
updateNodeDimensions: import("easy-peasy").Action<StoreModel, {
|
|
||||||
id: string;
|
|
||||||
nodeElement: HTMLDivElement;
|
|
||||||
}>;
|
|
||||||
updateNodePos: import("easy-peasy").Action<StoreModel, {
|
|
||||||
id: string;
|
|
||||||
pos: import("../types").XYPosition;
|
|
||||||
}>;
|
|
||||||
setSelection: import("easy-peasy").Action<StoreModel, boolean>;
|
|
||||||
setNodesSelection: import("easy-peasy").Action<StoreModel, {
|
|
||||||
isActive: boolean;
|
|
||||||
selection?: import("../types").SelectionRect | undefined;
|
|
||||||
}>;
|
|
||||||
setSelectedElements: import("easy-peasy").Action<StoreModel, import("../types").Node | import("../types").Edge | import("../types").Elements>;
|
|
||||||
updateSelection: import("easy-peasy").Action<StoreModel, import("../types").SelectionRect>;
|
|
||||||
updateTransform: import("easy-peasy").Action<StoreModel, {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
k: number;
|
|
||||||
}>;
|
|
||||||
updateSize: import("easy-peasy").Action<StoreModel, import("../types").Dimensions>;
|
|
||||||
initD3: import("easy-peasy").Action<StoreModel, {
|
|
||||||
zoom: import("d3-zoom").ZoomBehavior<Element, unknown>;
|
|
||||||
selection: import("d3-selection").Selection<Element, unknown, null, undefined>;
|
|
||||||
}>;
|
|
||||||
setSnapGrid: import("easy-peasy").Action<StoreModel, {
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
}>;
|
|
||||||
setConnectionPosition: import("easy-peasy").Action<StoreModel, import("../types").XYPosition>;
|
|
||||||
setConnectionSourceId: import("easy-peasy").Action<StoreModel, string | null>;
|
|
||||||
setInteractive: import("easy-peasy").Action<StoreModel, boolean>;
|
|
||||||
setUserSelection: import("easy-peasy").Action<StoreModel, import("../types").XYPosition>;
|
|
||||||
updateUserSelection: import("easy-peasy").Action<StoreModel, import("../types").XYPosition>;
|
|
||||||
unsetUserSelection: import("easy-peasy").Action<StoreModel, void>;
|
|
||||||
}, "1">) => Result) => Result;
|
|
||||||
export declare const useStoreDispatch: () => import("easy-peasy").Dispatch<StoreModel, import("redux").Action<any>>;
|
|
||||||
export declare const useStoreState: <Result>(mapState: (state: import("easy-peasy").StateMapper<{
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
transform: import("../types").Transform;
|
|
||||||
nodes: import("../types").Node[];
|
|
||||||
edges: import("../types").Edge[];
|
|
||||||
selectedElements: import("../types").Elements;
|
|
||||||
selectedNodesBbox: import("../types").Rect;
|
|
||||||
d3Zoom: import("d3-zoom").ZoomBehavior<Element, unknown> | null;
|
|
||||||
d3Selection: import("d3-selection").Selection<Element, unknown, null, undefined> | null;
|
|
||||||
d3Initialised: boolean;
|
|
||||||
nodesSelectionActive: boolean;
|
|
||||||
selectionActive: boolean;
|
|
||||||
selection: import("../types").SelectionRect | null;
|
|
||||||
userSelectionRect: import("../types").SelectionRect;
|
|
||||||
connectionSourceId: string | null;
|
|
||||||
connectionPosition: import("../types").XYPosition;
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
isInteractive: boolean;
|
|
||||||
onConnect: import("../types").OnConnectFunc;
|
|
||||||
}, "1">) => Result, equalityFn?: ((prev: Result, next: Result) => boolean) | undefined) => Result;
|
|
||||||
Vendored
-71
@@ -1,71 +0,0 @@
|
|||||||
import { Action } from 'easy-peasy';
|
|
||||||
import { Selection as D3Selection, ZoomBehavior } from 'd3';
|
|
||||||
import { ElementId, Elements, Transform, Node, Edge, Rect, Dimensions, XYPosition, OnConnectFunc, SelectionRect } from '../types';
|
|
||||||
declare type TransformXYK = {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
k: number;
|
|
||||||
};
|
|
||||||
declare type NodePosUpdate = {
|
|
||||||
id: ElementId;
|
|
||||||
pos: XYPosition;
|
|
||||||
};
|
|
||||||
declare type NodeDimensionUpdate = {
|
|
||||||
id: ElementId;
|
|
||||||
nodeElement: HTMLDivElement;
|
|
||||||
};
|
|
||||||
declare type SelectionUpdate = {
|
|
||||||
isActive: boolean;
|
|
||||||
selection?: SelectionRect;
|
|
||||||
};
|
|
||||||
declare type D3Init = {
|
|
||||||
zoom: ZoomBehavior<Element, unknown>;
|
|
||||||
selection: D3Selection<Element, unknown, null, undefined>;
|
|
||||||
};
|
|
||||||
declare type SetSnapGrid = {
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
};
|
|
||||||
export interface StoreModel {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
transform: Transform;
|
|
||||||
nodes: Node[];
|
|
||||||
edges: Edge[];
|
|
||||||
selectedElements: Elements;
|
|
||||||
selectedNodesBbox: Rect;
|
|
||||||
d3Zoom: ZoomBehavior<Element, unknown> | null;
|
|
||||||
d3Selection: D3Selection<Element, unknown, null, undefined> | null;
|
|
||||||
d3Initialised: boolean;
|
|
||||||
nodesSelectionActive: boolean;
|
|
||||||
selectionActive: boolean;
|
|
||||||
selection: SelectionRect | null;
|
|
||||||
userSelectionRect: SelectionRect;
|
|
||||||
connectionSourceId: ElementId | null;
|
|
||||||
connectionPosition: XYPosition;
|
|
||||||
snapToGrid: boolean;
|
|
||||||
snapGrid: [number, number];
|
|
||||||
isInteractive: boolean;
|
|
||||||
onConnect: OnConnectFunc;
|
|
||||||
setOnConnect: Action<StoreModel, OnConnectFunc>;
|
|
||||||
setNodes: Action<StoreModel, Node[]>;
|
|
||||||
setEdges: Action<StoreModel, Edge[]>;
|
|
||||||
updateNodeDimensions: Action<StoreModel, NodeDimensionUpdate>;
|
|
||||||
updateNodePos: Action<StoreModel, NodePosUpdate>;
|
|
||||||
setSelection: Action<StoreModel, boolean>;
|
|
||||||
setNodesSelection: Action<StoreModel, SelectionUpdate>;
|
|
||||||
setSelectedElements: Action<StoreModel, Elements | Node | Edge>;
|
|
||||||
updateSelection: Action<StoreModel, SelectionRect>;
|
|
||||||
updateTransform: Action<StoreModel, TransformXYK>;
|
|
||||||
updateSize: Action<StoreModel, Dimensions>;
|
|
||||||
initD3: Action<StoreModel, D3Init>;
|
|
||||||
setSnapGrid: Action<StoreModel, SetSnapGrid>;
|
|
||||||
setConnectionPosition: Action<StoreModel, XYPosition>;
|
|
||||||
setConnectionSourceId: Action<StoreModel, ElementId | null>;
|
|
||||||
setInteractive: Action<StoreModel, boolean>;
|
|
||||||
setUserSelection: Action<StoreModel, XYPosition>;
|
|
||||||
updateUserSelection: Action<StoreModel, XYPosition>;
|
|
||||||
unsetUserSelection: Action<StoreModel>;
|
|
||||||
}
|
|
||||||
declare const store: import("easy-peasy").Store<StoreModel, import("easy-peasy").EasyPeasyConfig<{}, any>>;
|
|
||||||
export default store;
|
|
||||||
Vendored
-134
@@ -1,134 +0,0 @@
|
|||||||
import { CSSProperties, SVGAttributes } from 'react';
|
|
||||||
export declare type ElementId = string;
|
|
||||||
export declare type Elements = Array<Node | Edge>;
|
|
||||||
export declare type Transform = [number, number, number];
|
|
||||||
export declare enum Position {
|
|
||||||
Left = "left",
|
|
||||||
Top = "top",
|
|
||||||
Right = "right",
|
|
||||||
Bottom = "bottom"
|
|
||||||
}
|
|
||||||
export declare type XYPosition = {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
};
|
|
||||||
export declare enum GridType {
|
|
||||||
Lines = "lines",
|
|
||||||
Dots = "dots"
|
|
||||||
}
|
|
||||||
export declare type HandleType = 'source' | 'target';
|
|
||||||
export declare type NodeTypesType = {
|
|
||||||
[key: string]: React.ReactNode;
|
|
||||||
};
|
|
||||||
export declare type EdgeTypesType = NodeTypesType;
|
|
||||||
export interface Dimensions {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
export interface Rect extends Dimensions, XYPosition {
|
|
||||||
}
|
|
||||||
export interface Box extends XYPosition {
|
|
||||||
x2: number;
|
|
||||||
y2: number;
|
|
||||||
}
|
|
||||||
export interface SelectionRect extends Rect {
|
|
||||||
startX: number;
|
|
||||||
startY: number;
|
|
||||||
draw: boolean;
|
|
||||||
}
|
|
||||||
export interface Node {
|
|
||||||
id: ElementId;
|
|
||||||
position: XYPosition;
|
|
||||||
type?: string;
|
|
||||||
__rg?: any;
|
|
||||||
data?: any;
|
|
||||||
style?: CSSProperties;
|
|
||||||
targetPosition?: Position;
|
|
||||||
sourcePosition?: Position;
|
|
||||||
}
|
|
||||||
export interface Edge {
|
|
||||||
id: ElementId;
|
|
||||||
type?: string;
|
|
||||||
source: ElementId;
|
|
||||||
target: ElementId;
|
|
||||||
style?: SVGAttributes<{}>;
|
|
||||||
animated?: boolean;
|
|
||||||
}
|
|
||||||
export interface EdgeProps {
|
|
||||||
sourceX: number;
|
|
||||||
sourceY: number;
|
|
||||||
targetX: number;
|
|
||||||
targetY: number;
|
|
||||||
style?: SVGAttributes<{}>;
|
|
||||||
}
|
|
||||||
export interface EdgeBezierProps extends EdgeProps {
|
|
||||||
sourcePosition: Position;
|
|
||||||
targetPosition: Position;
|
|
||||||
}
|
|
||||||
export interface NodeProps {
|
|
||||||
id: ElementId;
|
|
||||||
type: string;
|
|
||||||
data: any;
|
|
||||||
selected: boolean;
|
|
||||||
targetPosition?: Position;
|
|
||||||
sourcePosition?: Position;
|
|
||||||
style?: CSSProperties;
|
|
||||||
}
|
|
||||||
export interface NodeComponentProps {
|
|
||||||
id: ElementId;
|
|
||||||
type: string;
|
|
||||||
data: any;
|
|
||||||
selected?: boolean;
|
|
||||||
transform?: Transform;
|
|
||||||
xPos?: number;
|
|
||||||
yPos?: number;
|
|
||||||
targetPosition?: Position;
|
|
||||||
sourcePosition?: Position;
|
|
||||||
onClick?: (node: Node) => void | undefined;
|
|
||||||
onNodeDragStop?: () => any;
|
|
||||||
style?: CSSProperties;
|
|
||||||
}
|
|
||||||
export interface WrapNodeProps {
|
|
||||||
id: ElementId;
|
|
||||||
type: string;
|
|
||||||
data: any;
|
|
||||||
selected: boolean;
|
|
||||||
transform: Transform;
|
|
||||||
xPos: number;
|
|
||||||
yPos: number;
|
|
||||||
isInteractive: boolean;
|
|
||||||
onClick: (node: Node) => void | undefined;
|
|
||||||
onNodeDragStop: (node: Node) => void;
|
|
||||||
style?: CSSProperties;
|
|
||||||
sourcePosition?: Position;
|
|
||||||
targetPosition?: Position;
|
|
||||||
}
|
|
||||||
export declare type FitViewParams = {
|
|
||||||
padding: number;
|
|
||||||
};
|
|
||||||
export declare type FitViewFunc = (fitViewOptions: FitViewParams) => void;
|
|
||||||
declare type OnLoadParams = {
|
|
||||||
zoomIn: () => void;
|
|
||||||
zoomOut: () => void;
|
|
||||||
fitView: FitViewFunc;
|
|
||||||
};
|
|
||||||
export declare type OnLoadFunc = (params: OnLoadParams) => void;
|
|
||||||
export declare type Connection = {
|
|
||||||
source: ElementId | null;
|
|
||||||
target: ElementId | null;
|
|
||||||
};
|
|
||||||
export declare type OnConnectFunc = (params: Connection) => void;
|
|
||||||
export interface HandleElement extends XYPosition, Dimensions {
|
|
||||||
id?: ElementId | null;
|
|
||||||
position: Position;
|
|
||||||
}
|
|
||||||
export interface EdgeCompProps {
|
|
||||||
id: ElementId;
|
|
||||||
source: ElementId;
|
|
||||||
target: ElementId;
|
|
||||||
type: any;
|
|
||||||
onClick?: (edge: Edge) => void;
|
|
||||||
animated?: boolean;
|
|
||||||
selected?: boolean;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
Vendored
-15
@@ -1,15 +0,0 @@
|
|||||||
import { Node, Edge, Elements, Transform, XYPosition, Rect, FitViewParams } from '../types';
|
|
||||||
export declare const isEdge: (element: Node | Edge) => boolean;
|
|
||||||
export declare const isNode: (element: Node | Edge) => boolean;
|
|
||||||
export declare const getOutgoers: (node: Node, elements: Elements) => Elements;
|
|
||||||
export declare const removeElements: (elementsToRemove: Elements, elements: Elements) => Elements;
|
|
||||||
export declare const addEdge: (edgeParams: Edge, elements: Elements) => Elements;
|
|
||||||
export declare const parseElement: (element: Node | Edge, transform: Transform, snapToGrid: boolean, snapGrid: [number, number]) => Node | Edge;
|
|
||||||
export declare const getBoundsofRects: (rect1: Rect, rect2: Rect) => Rect;
|
|
||||||
export declare const getRectOfNodes: (nodes: Node[]) => Rect;
|
|
||||||
export declare const graphPosToZoomedPos: ({ x, y }: XYPosition, [tx, ty, tScale]: Transform) => XYPosition;
|
|
||||||
export declare const getNodesInside: (nodes: Node[], rect: Rect, [tx, ty, tScale]?: Transform, partially?: boolean) => Node[];
|
|
||||||
export declare const getConnectedEdges: (nodes: Node[], edges: Edge[]) => Edge[];
|
|
||||||
export declare const fitView: ({ padding }?: FitViewParams) => void;
|
|
||||||
export declare const zoomIn: () => void;
|
|
||||||
export declare const zoomOut: () => void;
|
|
||||||
Vendored
-6
@@ -1,6 +0,0 @@
|
|||||||
import { MouseEvent as ReactMouseEvent } from 'react';
|
|
||||||
export declare const isInputDOMNode: (e: MouseEvent | ReactMouseEvent<Element, MouseEvent> | ReactMouseEvent<HTMLElement | SVGElement, MouseEvent> | import("react").TouchEvent<HTMLElement | SVGElement> | TouchEvent | KeyboardEvent) => boolean;
|
|
||||||
export declare const getDimensions: (node: HTMLDivElement) => {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
};
|
|
||||||
@@ -11,7 +11,7 @@ const initialElements = [
|
|||||||
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
|
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
|
||||||
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
|
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
|
||||||
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
|
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
{ id: 'e1-2', source: '1', target: '2', animated: true, label: 'edge text' },
|
||||||
{ id: 'e1-3', source: '1', target: '3' },
|
{ id: 'e1-3', source: '1', target: '3' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
import ReactFlow, { removeElements, addEdge, MiniMap, Controls } from 'react-flow-renderer';
|
||||||
|
|
||||||
|
const onNodeDragStop = node => console.log('drag stop', node);
|
||||||
|
const onElementClick = element => console.log('click', element);
|
||||||
|
const onLoad = (graph) => {
|
||||||
|
graph.fitView();
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialElements = [
|
||||||
|
{ id: '1', type: 'input', data: { label: 'Input Node 1' }, position: { x: 250, y: 0 } },
|
||||||
|
{ id: '2', data: { label: 'Node 2' }, position: { x: 150, y: 100 } },
|
||||||
|
{ id: '3', data: { label: 'Node 3' }, position: { x: 250, y: 200 } },
|
||||||
|
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 300 } },
|
||||||
|
{ id: '5', data: { label: 'Node 5' }, position: { x: 450, y: 400 } },
|
||||||
|
{ id: '6', type: 'output', data: { label: 'Output Node 5' }, position: { x: 250, y: 550 } },
|
||||||
|
{ id: '7', type: 'output', data: { label: 'Output Node 6' }, position: { x: 550, y: 550 } },
|
||||||
|
{ id: 'e1-2', source: '1', target: '2', label: 'bezier edge', labelBgStyle: { fillOpacity: 0.75 } },
|
||||||
|
{ id: 'e2-3', source: '2', target: '3', type: 'step', label: 'step edge' },
|
||||||
|
{ id: 'e3-4', source: '3', target: '4', type: 'straight', label: 'straight edge' },
|
||||||
|
{ id: 'e3-5', source: '4', target: '5', animated: true, label: 'animated styled edge', style: { stroke: 'red' } },
|
||||||
|
{ id: 'e5-6', source: '5', target: '6', label: 'styled label', labelStyle: { fill: 'red', fontWeight: 700 } },
|
||||||
|
{ id: 'e5-7', source: '5', target: '7', label: 'label with styled bg', labelBgStyle: { fill: '#eee', fillOpacity: 0.7 } },
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
const EdgesFlow = () => {
|
||||||
|
const [elements, setElements] = useState(initialElements);
|
||||||
|
|
||||||
|
const onElementsRemove = (elementsToRemove) => setElements(els => removeElements(elementsToRemove, els));
|
||||||
|
const onConnect = (params) => setElements(els => addEdge(params, els));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactFlow
|
||||||
|
elements={elements}
|
||||||
|
onElementClick={onElementClick}
|
||||||
|
onElementsRemove={onElementsRemove}
|
||||||
|
onConnect={onConnect}
|
||||||
|
onNodeDragStop={onNodeDragStop}
|
||||||
|
style={{ width: '100%', height: '100%' }}
|
||||||
|
onLoad={onLoad}
|
||||||
|
snapToGrid={true}
|
||||||
|
>
|
||||||
|
<MiniMap />
|
||||||
|
<Controls />
|
||||||
|
</ReactFlow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EdgesFlow;
|
||||||
@@ -18,13 +18,13 @@ const initialElements = [
|
|||||||
sourcePosition: 'right'
|
sourcePosition: 'right'
|
||||||
},
|
},
|
||||||
{ id: '4', data: { label: 'Node 4' }, position: { x: 500, y: 200 }, targetPosition: 'left' },
|
{ id: '4', data: { label: 'Node 4' }, position: { x: 500, y: 200 }, targetPosition: 'left' },
|
||||||
{ id: '5', type: 'output', data: { label: 'Output Node 5'}, position: { x: 300, y: 300 } },
|
{ id: '5', type: 'output', data: { label: 'Output Node 5' }, position: { x: 300, y: 300 } },
|
||||||
{ id: '6', type: 'output', data: { label: 'Output Node 6' }, position: { x: 600, y: 400 } },
|
{ id: '6', type: 'output', data: { label: 'Output Node 6' }, position: { x: 600, y: 400 } },
|
||||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
{ id: 'e1-2', source: '1', target: '2', animated: true, label: 'edge text', labelBgStyle: { fillOpacity: 0.75 } },
|
||||||
{ id: 'e2-3', source: '2', target: '3', animated: true },
|
{ id: 'e2-3', source: '2', target: '3', animated: true },
|
||||||
{ id: 'e3-4', source: '3', target: '4', animated: true },
|
{ id: 'e3-4', source: '3', target: '4', animated: true },
|
||||||
{ id: 'e3-5', source: '4', target: '5', animated: true, type: 'step' },
|
{ id: 'e3-5', source: '4', target: '5', animated: true, type: 'step' },
|
||||||
{ id: 'e5-6b', source: '4', target: '6', type: 'step' },
|
{ id: 'e5-6b', source: '4', target: '6', type: 'step', label: 'styled label', labelStyle: { fill: 'red', fontWeight: 700 } },
|
||||||
]
|
]
|
||||||
|
|
||||||
const RichGraph = () => {
|
const RichGraph = () => {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import CustomNode from './CustomNode';
|
|||||||
import Stress from './Stress';
|
import Stress from './Stress';
|
||||||
import Inactive from './Inactive';
|
import Inactive from './Inactive';
|
||||||
import Empty from './Empty';
|
import Empty from './Empty';
|
||||||
|
import Edges from './Edges';
|
||||||
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
@@ -27,10 +28,14 @@ const routes = [{
|
|||||||
path: '/stress',
|
path: '/stress',
|
||||||
component: Stress,
|
component: Stress,
|
||||||
label: 'Stress'
|
label: 'Stress'
|
||||||
|
}, {
|
||||||
|
path: '/edges',
|
||||||
|
component: Edges,
|
||||||
|
label: 'Edges'
|
||||||
}, {
|
}, {
|
||||||
path: '/empty',
|
path: '/empty',
|
||||||
component: Empty
|
component: Empty
|
||||||
},{
|
}, {
|
||||||
path: '/inactive',
|
path: '/inactive',
|
||||||
component: Inactive
|
component: Inactive
|
||||||
}];
|
}];
|
||||||
|
|||||||
Generated
+2366
-2063
File diff suppressed because it is too large
Load Diff
+14
-12
@@ -10,7 +10,7 @@
|
|||||||
"url": "https://github.com/wbkd/react-flow.git"
|
"url": "https://github.com/wbkd/react-flow.git"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@welldone-software/why-did-you-render": "^4.1.3",
|
"@welldone-software/why-did-you-render": "^4.2.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"d3-selection": "^1.4.1",
|
"d3-selection": "^1.4.1",
|
||||||
"d3-zoom": "^1.8.3",
|
"d3-zoom": "^1.8.3",
|
||||||
@@ -20,14 +20,14 @@
|
|||||||
"resize-observer": "^1.0.0"
|
"resize-observer": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.9.0",
|
"@babel/core": "^7.9.6",
|
||||||
"@babel/preset-env": "^7.9.0",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@svgr/rollup": "^5.4.0",
|
"@svgr/rollup": "^5.4.0",
|
||||||
"@types/classnames": "^2.2.10",
|
"@types/classnames": "^2.2.10",
|
||||||
"@types/d3": "^5.7.2",
|
"@types/d3": "^5.7.2",
|
||||||
"@types/react": "^16.9.34",
|
"@types/react": "^16.9.35",
|
||||||
"@types/react-dom": "^16.9.6",
|
"@types/react-dom": "^16.9.8",
|
||||||
"autoprefixer": "^9.7.6",
|
"autoprefixer": "^9.7.6",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"babel-preset-react-app": "^9.1.2",
|
"babel-preset-react-app": "^9.1.2",
|
||||||
@@ -36,11 +36,12 @@
|
|||||||
"prettier": "2.0.5",
|
"prettier": "2.0.5",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"rollup": "^2.7.6",
|
"release-it": "^13.5.8",
|
||||||
|
"rollup": "^2.9.1",
|
||||||
"rollup-plugin-babel": "^4.4.0",
|
"rollup-plugin-babel": "^4.4.0",
|
||||||
"rollup-plugin-bundle-size": "^1.0.3",
|
"rollup-plugin-bundle-size": "^1.0.3",
|
||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-livereload": "^1.1.0",
|
"rollup-plugin-livereload": "^1.3.0",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
"rollup-plugin-peer-deps-external": "^2.2.2",
|
"rollup-plugin-peer-deps-external": "^2.2.2",
|
||||||
"rollup-plugin-postcss": "^3.1.1",
|
"rollup-plugin-postcss": "^3.1.1",
|
||||||
@@ -49,10 +50,9 @@
|
|||||||
"rollup-plugin-terser": "^5.3.0",
|
"rollup-plugin-terser": "^5.3.0",
|
||||||
"rollup-plugin-typescript2": "^0.27.0",
|
"rollup-plugin-typescript2": "^0.27.0",
|
||||||
"rollup-plugin-uglify": "^6.0.4",
|
"rollup-plugin-uglify": "^6.0.4",
|
||||||
"rollup-plugin-visualizer": "^4.0.4",
|
|
||||||
"start-server-and-test": "^1.11.0",
|
"start-server-and-test": "^1.11.0",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"wait-on": "^4.0.2"
|
"wait-on": "^5.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.13.1"
|
"react": "^16.13.1"
|
||||||
@@ -60,13 +60,15 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c --environment NODE_ENV:production",
|
"build": "rollup -c --environment NODE_ENV:production",
|
||||||
"start": "rollup -w -c",
|
"start": "rollup -w -c",
|
||||||
"dev": "npm start & cd example && npm start",
|
"waiton:dist": "wait-on dist/ReactFlow.js",
|
||||||
"build:example": "npm install && cd example && npm install && npm run build",
|
"dev": "npm start & npm run waiton:dist && cd example && npm start",
|
||||||
"dev:wait": "start-server-and-test dev http-get://localhost:3000",
|
"dev:wait": "start-server-and-test dev http-get://localhost:3000",
|
||||||
|
"build:example": "npm install && npm run build && cd example && npm install && npm run build",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"cy:open": "cypress open",
|
"cy:open": "cypress open",
|
||||||
"cypress": "npm run dev:wait cy:open",
|
"cypress": "npm run dev:wait cy:open",
|
||||||
"test": "npm run dev:wait cy:run"
|
"test": "npm run dev:wait cy:run",
|
||||||
|
"release": "release-it"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
+44
-41
@@ -3,52 +3,55 @@ import commonjs from 'rollup-plugin-commonjs';
|
|||||||
import babel from 'rollup-plugin-babel';
|
import babel from 'rollup-plugin-babel';
|
||||||
import postcss from 'rollup-plugin-postcss';
|
import postcss from 'rollup-plugin-postcss';
|
||||||
import bundleSize from 'rollup-plugin-bundle-size';
|
import bundleSize from 'rollup-plugin-bundle-size';
|
||||||
import visualizer from 'rollup-plugin-visualizer';
|
|
||||||
import replace from 'rollup-plugin-replace';
|
import replace from 'rollup-plugin-replace';
|
||||||
import svgr from '@svgr/rollup';
|
import svgr from '@svgr/rollup';
|
||||||
import typescript from 'rollup-plugin-typescript2'
|
import typescript from 'rollup-plugin-typescript2';
|
||||||
|
|
||||||
import pkg from './package.json';
|
import pkg from './package.json';
|
||||||
|
|
||||||
const isProd = process.env.NODE_ENV === 'production';
|
const isProd = process.env.NODE_ENV === 'production';
|
||||||
const processEnv = isProd ? 'production' : 'development';
|
const processEnv = isProd ? 'production' : 'development';
|
||||||
|
|
||||||
export default [{
|
export default [
|
||||||
input: 'src/index.ts',
|
{
|
||||||
external: ['react', 'react-dom'],
|
input: 'src/index.ts',
|
||||||
onwarn(warning, rollupWarn) {
|
external: ['react', 'react-dom'],
|
||||||
if (warning.code !== 'CIRCULAR_DEPENDENCY') {
|
onwarn(warning, rollupWarn) {
|
||||||
rollupWarn(warning);
|
if (warning.code !== 'CIRCULAR_DEPENDENCY') {
|
||||||
}
|
rollupWarn(warning);
|
||||||
},
|
}
|
||||||
output: [{
|
},
|
||||||
file: pkg.main,
|
output: [
|
||||||
format: 'cjs',
|
{
|
||||||
sourcemap: true,
|
file: pkg.main,
|
||||||
exports: 'named'
|
format: 'cjs',
|
||||||
}, {
|
sourcemap: true,
|
||||||
file: pkg.module,
|
exports: 'named',
|
||||||
format: 'esm',
|
},
|
||||||
sourcemap: true,
|
{
|
||||||
exports: 'named'
|
file: pkg.module,
|
||||||
}],
|
format: 'esm',
|
||||||
plugins: [
|
sourcemap: true,
|
||||||
bundleSize(),
|
exports: 'named',
|
||||||
postcss(),
|
},
|
||||||
babel({
|
],
|
||||||
exclude: 'node_modules/**'
|
plugins: [
|
||||||
}),
|
bundleSize(),
|
||||||
visualizer(),
|
postcss(),
|
||||||
replace({
|
babel({
|
||||||
'process.env.NODE_ENV': JSON.stringify(processEnv)
|
exclude: 'node_modules/**',
|
||||||
}),
|
}),
|
||||||
svgr(),
|
replace({
|
||||||
typescript({
|
'process.env.NODE_ENV': JSON.stringify(processEnv),
|
||||||
clean: true
|
}),
|
||||||
}),
|
svgr(),
|
||||||
resolve(),
|
typescript({
|
||||||
commonjs({
|
clean: true,
|
||||||
include: 'node_modules/**'
|
}),
|
||||||
}),
|
resolve(),
|
||||||
]
|
commonjs({
|
||||||
}];
|
include: 'node_modules/**',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
|
import EdgeText from './EdgeText';
|
||||||
import { EdgeBezierProps, Position } from '../../types';
|
import { EdgeBezierProps, Position } from '../../types';
|
||||||
|
|
||||||
export default memo(
|
export default memo(
|
||||||
@@ -10,23 +11,43 @@ export default memo(
|
|||||||
targetY,
|
targetY,
|
||||||
sourcePosition = Position.Bottom,
|
sourcePosition = Position.Bottom,
|
||||||
targetPosition = Position.Top,
|
targetPosition = Position.Top,
|
||||||
|
label,
|
||||||
|
labelStyle,
|
||||||
|
labelShowBg,
|
||||||
|
labelBgStyle,
|
||||||
style = {},
|
style = {},
|
||||||
}: EdgeBezierProps) => {
|
}: EdgeBezierProps) => {
|
||||||
const yOffset = Math.abs(targetY - sourceY) / 2;
|
const yOffset = Math.abs(targetY - sourceY) / 2;
|
||||||
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
||||||
|
|
||||||
|
const xOffset = Math.abs(targetX - sourceX) / 2;
|
||||||
|
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
||||||
|
|
||||||
let dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
|
let dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
|
||||||
|
|
||||||
const leftAndRight = [Position.Left, Position.Right];
|
const leftAndRight = [Position.Left, Position.Right];
|
||||||
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
|
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
|
||||||
const xOffset = Math.abs(targetX - sourceX) / 2;
|
|
||||||
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
|
||||||
|
|
||||||
dAttr = `M${sourceX},${sourceY} C${centerX},${sourceY} ${centerX},${targetY} ${targetX},${targetY}`;
|
dAttr = `M${sourceX},${sourceY} C${centerX},${sourceY} ${centerX},${targetY} ${targetX},${targetY}`;
|
||||||
} else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) {
|
} else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) {
|
||||||
dAttr = `M${sourceX},${sourceY} C${sourceX},${targetY} ${sourceX},${targetY} ${targetX},${targetY}`;
|
dAttr = `M${sourceX},${sourceY} C${sourceX},${targetY} ${sourceX},${targetY} ${targetX},${targetY}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <path {...style} d={dAttr} />;
|
const text = label ? (
|
||||||
|
<EdgeText
|
||||||
|
x={centerX}
|
||||||
|
y={centerY}
|
||||||
|
label={label}
|
||||||
|
labelStyle={labelStyle}
|
||||||
|
labelShowBg={labelShowBg}
|
||||||
|
labelBgStyle={labelBgStyle}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g>
|
||||||
|
<path style={style} d={dAttr} className="react-flow__edge-path" />
|
||||||
|
{text}
|
||||||
|
</g>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import React, { memo, useRef, useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import { EdgeTextProps, Rect } from '../../types';
|
||||||
|
|
||||||
|
const textBgPadding = 2;
|
||||||
|
|
||||||
|
export default memo(({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {} }: EdgeTextProps) => {
|
||||||
|
const edgeRef = useRef<SVGTextElement>(null);
|
||||||
|
const [edgeTextBbox, setEdgeTextBbox] = useState<Rect>({ x: 0, y: 0, width: 0, height: 0 });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (edgeRef.current) {
|
||||||
|
const textBbox = edgeRef.current.getBBox();
|
||||||
|
setEdgeTextBbox({
|
||||||
|
x: textBbox.x,
|
||||||
|
y: textBbox.y,
|
||||||
|
width: textBbox.width,
|
||||||
|
height: textBbox.height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (typeof label === 'undefined' || !label) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g transform={`translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`}>
|
||||||
|
{labelShowBg && (
|
||||||
|
<rect
|
||||||
|
width={edgeTextBbox.width + 2 * textBgPadding}
|
||||||
|
x={-textBgPadding}
|
||||||
|
y={-textBgPadding}
|
||||||
|
height={edgeTextBbox.height + 2 * textBgPadding}
|
||||||
|
className="react-flow__edge-textbg"
|
||||||
|
style={labelBgStyle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<text className="react-flow__edge-text" y={edgeTextBbox.height / 2} dy="0.3em" ref={edgeRef} style={labelStyle}>
|
||||||
|
{label}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -1,17 +1,36 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
|
import EdgeText from './EdgeText';
|
||||||
import { EdgeProps } from '../../types';
|
import { EdgeProps } from '../../types';
|
||||||
|
|
||||||
export default memo(
|
export default memo(
|
||||||
({ sourceX, sourceY, targetX, targetY, style = {} }: EdgeProps) => {
|
({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style = {} }: EdgeProps) => {
|
||||||
const yOffset = Math.abs(targetY - sourceY) / 2;
|
const yOffset = Math.abs(targetY - sourceY) / 2;
|
||||||
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
||||||
|
|
||||||
return (
|
const xOffset = Math.abs(targetX - sourceX) / 2;
|
||||||
<path
|
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
||||||
{...style}
|
|
||||||
d={`M ${sourceX},${sourceY}L ${sourceX},${centerY}L ${targetX},${centerY}L ${targetX},${targetY}`}
|
const text = label ? (
|
||||||
|
<EdgeText
|
||||||
|
x={centerX}
|
||||||
|
y={centerY}
|
||||||
|
label={label}
|
||||||
|
labelStyle={labelStyle}
|
||||||
|
labelShowBg={labelShowBg}
|
||||||
|
labelBgStyle={labelBgStyle}
|
||||||
/>
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
style={style}
|
||||||
|
className="react-flow__edge-path"
|
||||||
|
d={`M ${sourceX},${sourceY}L ${sourceX},${centerY}L ${targetX},${centerY}L ${targetX},${targetY}`}
|
||||||
|
/>
|
||||||
|
{text}
|
||||||
|
</g>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,32 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
|
import EdgeText from './EdgeText';
|
||||||
import { EdgeProps } from '../../types';
|
import { EdgeProps } from '../../types';
|
||||||
|
|
||||||
export default memo(
|
export default memo(
|
||||||
({ sourceX, sourceY, targetX, targetY, style = {} }: EdgeProps) => {
|
({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style = {} }: EdgeProps) => {
|
||||||
|
const yOffset = Math.abs(targetY - sourceY) / 2;
|
||||||
|
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
||||||
|
|
||||||
|
const xOffset = Math.abs(targetX - sourceX) / 2;
|
||||||
|
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
||||||
|
|
||||||
|
const text = label ? (
|
||||||
|
<EdgeText
|
||||||
|
x={centerX}
|
||||||
|
y={centerY}
|
||||||
|
label={label}
|
||||||
|
labelStyle={labelStyle}
|
||||||
|
labelShowBg={labelShowBg}
|
||||||
|
labelBgStyle={labelBgStyle}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<path {...style} d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} />
|
<g>
|
||||||
|
<path style={style} className="react-flow__edge-path" d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} />
|
||||||
|
{text}
|
||||||
|
</g>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { memo, ComponentType } from 'react';
|
import React, { memo, ComponentType, CSSProperties } from 'react';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
|
|
||||||
import store from '../../store';
|
import store from '../../store';
|
||||||
@@ -9,6 +9,10 @@ interface EdgeWrapperProps {
|
|||||||
source: ElementId;
|
source: ElementId;
|
||||||
target: ElementId;
|
target: ElementId;
|
||||||
type: any;
|
type: any;
|
||||||
|
label?: string;
|
||||||
|
labelStyle?: CSSProperties;
|
||||||
|
labelShowBg?: boolean;
|
||||||
|
labelBgStyle: CSSProperties;
|
||||||
onClick: (edge: Edge) => void;
|
onClick: (edge: Edge) => void;
|
||||||
animated: boolean;
|
animated: boolean;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
@@ -17,7 +21,21 @@ interface EdgeWrapperProps {
|
|||||||
|
|
||||||
export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
|
export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
|
||||||
const EdgeWrapper = memo(
|
const EdgeWrapper = memo(
|
||||||
({ id, source, target, type, animated, selected, onClick, isInteractive, ...rest }: EdgeWrapperProps) => {
|
({
|
||||||
|
id,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
type,
|
||||||
|
animated,
|
||||||
|
selected,
|
||||||
|
onClick,
|
||||||
|
isInteractive,
|
||||||
|
label,
|
||||||
|
labelStyle,
|
||||||
|
labelShowBg,
|
||||||
|
labelBgStyle,
|
||||||
|
...rest
|
||||||
|
}: EdgeWrapperProps) => {
|
||||||
const edgeClasses = cx('react-flow__edge', { selected, animated });
|
const edgeClasses = cx('react-flow__edge', { selected, animated });
|
||||||
const onEdgeClick = (): void => {
|
const onEdgeClick = (): void => {
|
||||||
if (!isInteractive) {
|
if (!isInteractive) {
|
||||||
@@ -38,6 +56,10 @@ export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
|
|||||||
animated={animated}
|
animated={animated}
|
||||||
selected={selected}
|
selected={selected}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
label={label}
|
||||||
|
labelStyle={labelStyle}
|
||||||
|
labelShowBg={labelShowBg}
|
||||||
|
labelBgStyle={labelBgStyle}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ function getHandle(bounds: HandleElement[], handleId: ElementId | null): HandleE
|
|||||||
if (bounds.length === 1 || !handleId) {
|
if (bounds.length === 1 || !handleId) {
|
||||||
handle = bounds[0];
|
handle = bounds[0];
|
||||||
} else if (handleId) {
|
} else if (handleId) {
|
||||||
handle = bounds.find(d => d.id === handleId);
|
handle = bounds.find((d) => d.id === handleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
@@ -123,8 +123,8 @@ function renderEdge(
|
|||||||
const [sourceId, sourceHandleId] = edge.source.split('__');
|
const [sourceId, sourceHandleId] = edge.source.split('__');
|
||||||
const [targetId, targetHandleId] = edge.target.split('__');
|
const [targetId, targetHandleId] = edge.target.split('__');
|
||||||
|
|
||||||
const sourceNode = nodes.find(n => n.id === sourceId);
|
const sourceNode = nodes.find((n) => n.id === sourceId);
|
||||||
const targetNode = nodes.find(n => n.id === targetId);
|
const targetNode = nodes.find((n) => n.id === targetId);
|
||||||
|
|
||||||
if (!sourceNode) {
|
if (!sourceNode) {
|
||||||
throw new Error(`couldn't create edge for source id: ${sourceId}`);
|
throw new Error(`couldn't create edge for source id: ${sourceId}`);
|
||||||
@@ -155,7 +155,7 @@ function renderEdge(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isSelected = (selectedElements as Edge[]).some(
|
const isSelected = (selectedElements as Edge[]).some(
|
||||||
elm => isEdge(elm) && elm.source === sourceId && elm.target === targetId
|
(elm) => isEdge(elm) && elm.source === sourceId && elm.target === targetId
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -166,6 +166,10 @@ function renderEdge(
|
|||||||
onClick={props.onElementClick}
|
onClick={props.onElementClick}
|
||||||
selected={isSelected}
|
selected={isSelected}
|
||||||
animated={edge.animated}
|
animated={edge.animated}
|
||||||
|
label={edge.label}
|
||||||
|
labelStyle={edge.labelStyle}
|
||||||
|
labelShowBg={edge.labelShowBg}
|
||||||
|
labelBgStyle={edge.labelBgStyle}
|
||||||
style={edge.style}
|
style={edge.style}
|
||||||
source={sourceId}
|
source={sourceId}
|
||||||
target={targetId}
|
target={targetId}
|
||||||
@@ -191,7 +195,7 @@ const EdgeRenderer = memo((props: EdgeRendererProps) => {
|
|||||||
connectionPosition: { x, y },
|
connectionPosition: { x, y },
|
||||||
selectedElements,
|
selectedElements,
|
||||||
isInteractive,
|
isInteractive,
|
||||||
} = useStoreState(s => ({
|
} = useStoreState((s) => ({
|
||||||
transform: s.transform,
|
transform: s.transform,
|
||||||
edges: s.edges,
|
edges: s.edges,
|
||||||
nodes: s.nodes,
|
nodes: s.nodes,
|
||||||
|
|||||||
+20
-8
@@ -46,16 +46,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.react-flow__edge {
|
.react-flow__edge {
|
||||||
fill: none;
|
|
||||||
stroke: #bbb;
|
|
||||||
stroke-width: 2;
|
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
&.selected {
|
&.animated path {
|
||||||
stroke: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.animated {
|
|
||||||
stroke-dasharray: 5;
|
stroke-dasharray: 5;
|
||||||
animation: dashdraw 0.5s linear infinite;
|
animation: dashdraw 0.5s linear infinite;
|
||||||
}
|
}
|
||||||
@@ -66,6 +59,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.react-flow__edge-path {
|
||||||
|
fill: none;
|
||||||
|
stroke: #bbb;
|
||||||
|
stroke-width: 2;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
stroke: #555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-flow__edge-text {
|
||||||
|
font-size: 12px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-flow__edge-textbg {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes dashdraw {
|
@keyframes dashdraw {
|
||||||
from {
|
from {
|
||||||
stroke-dashoffset: 10;
|
stroke-dashoffset: 10;
|
||||||
|
|||||||
+24
-3
@@ -1,4 +1,4 @@
|
|||||||
import { CSSProperties, SVGAttributes } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
|
|
||||||
export type ElementId = string;
|
export type ElementId = string;
|
||||||
|
|
||||||
@@ -63,7 +63,11 @@ export interface Edge {
|
|||||||
type?: string;
|
type?: string;
|
||||||
source: ElementId;
|
source: ElementId;
|
||||||
target: ElementId;
|
target: ElementId;
|
||||||
style?: SVGAttributes<{}>;
|
label?: string;
|
||||||
|
labelStyle?: CSSProperties;
|
||||||
|
labelShowBg?: boolean;
|
||||||
|
labelBgStyle?: CSSProperties;
|
||||||
|
style?: CSSProperties;
|
||||||
animated?: boolean;
|
animated?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +76,11 @@ export interface EdgeProps {
|
|||||||
sourceY: number;
|
sourceY: number;
|
||||||
targetX: number;
|
targetX: number;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
style?: SVGAttributes<{}>;
|
label?: string;
|
||||||
|
labelStyle?: CSSProperties;
|
||||||
|
labelShowBg?: boolean;
|
||||||
|
labelBgStyle?: CSSProperties;
|
||||||
|
style?: CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EdgeBezierProps extends EdgeProps {
|
export interface EdgeBezierProps extends EdgeProps {
|
||||||
@@ -151,7 +159,20 @@ export interface EdgeCompProps {
|
|||||||
source: ElementId;
|
source: ElementId;
|
||||||
target: ElementId;
|
target: ElementId;
|
||||||
type: any;
|
type: any;
|
||||||
|
label?: string;
|
||||||
|
labelStyle?: CSSProperties;
|
||||||
|
labelShowBg?: boolean;
|
||||||
|
labelBgStyle?: CSSProperties;
|
||||||
onClick?: (edge: Edge) => void;
|
onClick?: (edge: Edge) => void;
|
||||||
animated?: boolean;
|
animated?: boolean;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EdgeTextProps {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
label?: string;
|
||||||
|
labelStyle?: CSSProperties;
|
||||||
|
labelShowBg?: boolean;
|
||||||
|
labelBgStyle?: CSSProperties;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user