diff --git a/examples/nextjs/pages/EdgeRouting/index.tsx b/examples/nextjs/pages/EdgeRouting/index.tsx new file mode 100644 index 00000000..5e68a840 --- /dev/null +++ b/examples/nextjs/pages/EdgeRouting/index.tsx @@ -0,0 +1,132 @@ +import React from 'react'; +import ReactFlow, { Node, Edge, Position, MarkerType } from 'reactflow'; + +const nodes: Node[] = [ + // LTR + { + id: '1', + position: { x: 50, y: -100 }, + data: { label: 'Source' }, + sourcePosition: Position.Right, + targetPosition: Position.Right, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + { + id: '2', + position: { x: -100, y: 0 }, + data: { label: 'Target' }, + sourcePosition: Position.Left, + targetPosition: Position.Left, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + // Right Right + { + id: '3', + position: { x: -100, y: 250 }, + data: { label: 'Source' }, + sourcePosition: Position.Right, + targetPosition: Position.Right, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + { + id: '4', + position: { x: 50, y: 150 }, + data: { label: 'Target' }, + sourcePosition: Position.Right, + targetPosition: Position.Right, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + // Right Top + { + id: '5', + position: { x: -100, y: 450 }, + data: { label: 'Source' }, + sourcePosition: Position.Right, + targetPosition: Position.Right, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + { + id: '6', + position: { x: 100, y: 400 }, + data: { label: 'Target' }, + sourcePosition: Position.Top, + targetPosition: Position.Top, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + // Right Bottom + { + id: '7', + position: { x: 100, y: 700 }, + data: { label: 'Source' }, + sourcePosition: Position.Right, + targetPosition: Position.Right, + style: { background: 'rgba(255,255,255,0.5)' }, + }, + { + id: '8', + position: { x: -100, y: 600 }, + data: { label: 'Target' }, + sourcePosition: Position.Bottom, + targetPosition: Position.Bottom, + style: { background: 'rgba(255,255,255,0.5)' }, + }, +]; + +const edges: Edge[] = [ + { + id: 'e1-2', + source: '1', + target: '2', + type: 'smoothstep', + markerEnd: { + type: MarkerType.ArrowClosed, + }, + options: { + offset: 30, + }, + }, + { + id: 'e3-4', + source: '3', + target: '4', + type: 'smoothstep', + markerEnd: { + type: MarkerType.ArrowClosed, + }, + options: { + borderRadius: 2, + }, + }, + + { + id: 'e4-5', + source: '5', + target: '6', + type: 'smoothstep', + markerEnd: { + type: MarkerType.ArrowClosed, + }, + }, + + { + id: 'e7-8', + source: '7', + target: '8', + type: 'smoothstep', + markerEnd: { + type: MarkerType.ArrowClosed, + }, + }, +]; + +const defaultEdgeOptions = { + style: { + strokeWidth: 2, + }, +}; + +const SimpleEdge = () => { + return ; +}; + +export default SimpleEdge; diff --git a/examples/nextjs/pages/EdgeTypes/index.tsx b/examples/nextjs/pages/EdgeTypes/index.tsx index 7e87d780..6a93d1b1 100644 --- a/examples/nextjs/pages/EdgeTypes/index.tsx +++ b/examples/nextjs/pages/EdgeTypes/index.tsx @@ -41,7 +41,6 @@ const EdgeTypesFlow = () => { onInit={onInit} onConnect={onConnect} minZoom={0.2} - zoomOnScroll={false} selectionKeyCode="a+s" multiSelectionKeyCode={multiSelectionKeyCode} deleteKeyCode={deleteKeyCode} diff --git a/examples/nextjs/pages/Undirectional/index.tsx b/examples/nextjs/pages/Undirectional/index.tsx index 5037161d..4ea676a5 100644 --- a/examples/nextjs/pages/Undirectional/index.tsx +++ b/examples/nextjs/pages/Undirectional/index.tsx @@ -80,7 +80,7 @@ const initialEdges: Edge[] = [ target: '01', sourceHandle: 'left', targetHandle: 'bottom', - type: 'default', + type: 'smoothstep', }, { id: 'e0-1b', @@ -88,7 +88,7 @@ const initialEdges: Edge[] = [ target: '01', sourceHandle: 'top', targetHandle: 'right', - type: 'default', + type: 'smoothstep', }, { id: 'e0-2a', @@ -96,7 +96,7 @@ const initialEdges: Edge[] = [ target: '02', sourceHandle: 'top', targetHandle: 'left', - type: 'default', + type: 'smoothstep', }, { id: 'e0-2b', @@ -104,7 +104,7 @@ const initialEdges: Edge[] = [ target: '02', sourceHandle: 'right', targetHandle: 'bottom', - type: 'default', + type: 'smoothstep', }, { id: 'e0-3a', @@ -112,7 +112,7 @@ const initialEdges: Edge[] = [ target: '03', sourceHandle: 'right', targetHandle: 'top', - type: 'default', + type: 'smoothstep', }, { id: 'e0-3b', @@ -120,7 +120,7 @@ const initialEdges: Edge[] = [ target: '03', sourceHandle: 'bottom', targetHandle: 'left', - type: 'default', + type: 'smoothstep', }, { id: 'e0-4a', @@ -128,7 +128,7 @@ const initialEdges: Edge[] = [ target: '04', sourceHandle: 'bottom', targetHandle: 'right', - type: 'default', + type: 'smoothstep', }, { id: 'e0-4b', @@ -136,7 +136,7 @@ const initialEdges: Edge[] = [ target: '04', sourceHandle: 'left', targetHandle: 'top', - type: 'default', + type: 'smoothstep', }, { id: 'e0-10', @@ -144,7 +144,7 @@ const initialEdges: Edge[] = [ target: '10', sourceHandle: 'top', targetHandle: 'bottom', - type: 'default', + type: 'smoothstep', }, { id: 'e0-20', @@ -152,7 +152,7 @@ const initialEdges: Edge[] = [ target: '20', sourceHandle: 'right', targetHandle: 'left', - type: 'default', + type: 'smoothstep', }, { id: 'e0-30', @@ -160,7 +160,7 @@ const initialEdges: Edge[] = [ target: '30', sourceHandle: 'bottom', targetHandle: 'top', - type: 'default', + type: 'smoothstep', }, { id: 'e0-40', @@ -168,7 +168,7 @@ const initialEdges: Edge[] = [ target: '40', sourceHandle: 'left', targetHandle: 'right', - type: 'default', + type: 'smoothstep', }, ]; diff --git a/examples/nextjs/pages/_app.tsx b/examples/nextjs/pages/_app.tsx index 1d4fb176..79429551 100755 --- a/examples/nextjs/pages/_app.tsx +++ b/examples/nextjs/pages/_app.tsx @@ -1,5 +1,7 @@ -import React from 'react'; +import React, { ChangeEventHandler } from 'react'; import { useRouter } from 'next/router'; +import { AppProps } from 'next/app'; + import '../styles/globals.css'; // Unfortunately this doesn't work because preconsruct clears the dist folder and there is @@ -18,6 +20,7 @@ const routes = [ '/DefaultNodes', '/DragHandle', '/DragNDrop', + '/EdgeRouting', '/EdgeTypes', '/Edges', '/Empty', @@ -45,10 +48,10 @@ const routes = [ '/Validation', ]; -function MyApp({ Component, pageProps }) { +function App({ Component, pageProps }: AppProps) { const router = useRouter(); - const onRouteChange = (evt) => { + const onRouteChange: ChangeEventHandler = (evt) => { router.push(evt.target.value); }; @@ -71,4 +74,4 @@ function MyApp({ Component, pageProps }) { ); } -export default MyApp; +export default App; diff --git a/packages/core/src/components/Edges/BezierEdge.tsx b/packages/core/src/components/Edges/BezierEdge.tsx index 825265cb..f805fecd 100644 --- a/packages/core/src/components/Edges/BezierEdge.tsx +++ b/packages/core/src/components/Edges/BezierEdge.tsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import { EdgeProps, Position } from '../../types'; +import { BezierEdgeProps, Position } from '../../types'; import BaseEdge from './BaseEdge'; export interface GetBezierPathParams { @@ -143,8 +143,8 @@ const BezierEdge = memo( style, markerEnd, markerStart, - curvature, - }: EdgeProps) => { + options, + }: BezierEdgeProps) => { const params = { sourceX, sourceY, @@ -152,7 +152,7 @@ const BezierEdge = memo( targetX, targetY, targetPosition, - curvature, + curvature: options?.curvature, }; const path = getBezierPath(params); const [centerX, centerY] = getBezierCenter(params); diff --git a/packages/core/src/components/Edges/SmoothStepEdge.tsx b/packages/core/src/components/Edges/SmoothStepEdge.tsx index 161eb8d5..80582b8b 100644 --- a/packages/core/src/components/Edges/SmoothStepEdge.tsx +++ b/packages/core/src/components/Edges/SmoothStepEdge.tsx @@ -1,26 +1,9 @@ import { memo } from 'react'; import { getCenter } from './utils'; -import { EdgeSmoothStepProps, Position } from '../../types'; +import { SmoothStepEdgeProps, Position, XYPosition } from '../../types'; import BaseEdge from './BaseEdge'; -// These are some helper methods for drawing the round corners -// The name indicates the direction of the path. "bottomLeftCorner" goes -// from bottom to the left and "leftBottomCorner" goes from left to the bottom. -// We have to consider the direction of the paths because of the animated lines. -const bottomLeftCorner = (x: number, y: number, size: number): string => - `L ${x},${y - size}Q ${x},${y} ${x + size},${y}`; -const leftBottomCorner = (x: number, y: number, size: number): string => - `L ${x + size},${y}Q ${x},${y} ${x},${y - size}`; -const bottomRightCorner = (x: number, y: number, size: number): string => - `L ${x},${y - size}Q ${x},${y} ${x - size},${y}`; -const rightBottomCorner = (x: number, y: number, size: number): string => - `L ${x - size},${y}Q ${x},${y} ${x},${y - size}`; -const leftTopCorner = (x: number, y: number, size: number): string => `L ${x + size},${y}Q ${x},${y} ${x},${y + size}`; -const topLeftCorner = (x: number, y: number, size: number): string => `L ${x},${y + size}Q ${x},${y} ${x + size},${y}`; -const topRightCorner = (x: number, y: number, size: number): string => `L ${x},${y + size}Q ${x},${y} ${x - size},${y}`; -const rightTopCorner = (x: number, y: number, size: number): string => `L ${x - size},${y}Q ${x},${y} ${x},${y + size}`; - export interface GetSmoothStepPathParams { sourceX: number; sourceY: number; @@ -31,6 +14,135 @@ export interface GetSmoothStepPathParams { borderRadius?: number; centerX?: number; centerY?: number; + offset?: number; +} + +const handleDirections = { + [Position.Left]: { x: -1, y: 0 }, + [Position.Right]: { x: 1, y: 0 }, + [Position.Top]: { x: 0, y: -1 }, + [Position.Bottom]: { x: 0, y: 1 }, +}; + +const getDirection = ({ + source, + sourcePosition = Position.Bottom, + target, +}: { + source: XYPosition; + sourcePosition: Position; + target: XYPosition; +}): XYPosition => { + if (sourcePosition === Position.Left || sourcePosition === Position.Right) { + return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 }; + } + return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 }; +}; + +const distance = (a: XYPosition, b: XYPosition) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)); + +// ith this function we try to mimic a orthogonal edge routing behaviour +// It's not as good as a real orthogonal edge routing but it's faster and good enough as a default for step and smooth step edges +function getPoints({ + source, + sourcePosition = Position.Bottom, + target, + targetPosition = Position.Top, + center, + offset, +}: { + source: XYPosition; + sourcePosition: Position; + target: XYPosition; + targetPosition: Position; + center: XYPosition; + offset: number; +}): XYPosition[] { + const sourceDir = handleDirections[sourcePosition]; + const targetDir = handleDirections[targetPosition]; + const sourceGapped: XYPosition = { x: source.x + sourceDir.x * offset, y: source.y + sourceDir.y * offset }; + const targetGapped: XYPosition = { x: target.x + targetDir.x * offset, y: target.y + targetDir.y * offset }; + const dir = getDirection({ + source: sourceGapped, + sourcePosition, + target: targetGapped, + }); + const dirAccessor = dir.x !== 0 ? 'x' : 'y'; + const currDir = dir[dirAccessor]; + + let points: XYPosition[] = []; + + // opposite handle positions, default case + if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) { + // ---> + // | + // >--- + const verticalSplit: XYPosition[] = [ + { x: center.x, y: sourceGapped.y }, + { x: center.x, y: targetGapped.y }, + ]; + // | + // --- + // | + const horizontalSplit: XYPosition[] = [ + { x: sourceGapped.x, y: center.y }, + { x: targetGapped.x, y: center.y }, + ]; + + if (sourceDir[dirAccessor] === currDir) { + points = dirAccessor === 'x' ? verticalSplit : horizontalSplit; + } else { + points = dirAccessor === 'x' ? horizontalSplit : verticalSplit; + } + } else { + // sourceTarget means we take x from source and y from target, targetSource is the opposite + const sourceTarget: XYPosition[] = [{ x: sourceGapped.x, y: targetGapped.y }]; + const targetSource: XYPosition[] = [{ x: targetGapped.x, y: sourceGapped.y }]; + // this handles edges with same handle positions + if (dirAccessor === 'x') { + points = sourceDir.x === currDir ? targetSource : sourceTarget; + } else { + points = sourceDir.y === currDir ? sourceTarget : targetSource; + } + + // these are conditions for handling mixed handle positions like Right -> Bottom for example + if (sourcePosition !== targetPosition) { + const dirAccessorOpposite = dirAccessor === 'x' ? 'y' : 'x'; + const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite]; + const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite]; + const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite]; + const flipSourceTarget = + (sourceDir[dirAccessor] === 1 && ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) || + (sourceDir[dirAccessor] !== 1 && ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo))); + + if (flipSourceTarget) { + points = dirAccessor === 'x' ? sourceTarget : targetSource; + } + } + } + + return [source, sourceGapped, ...points, targetGapped, target]; +} + +function getBend(a: XYPosition, b: XYPosition, c: XYPosition, size: number): string { + const bendSize = Math.min(distance(a, b) / 2, distance(b, c) / 2, size); + const { x, y } = b; + + // no bend + if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) { + return `L${x} ${y}`; + } + + // first segment is horizontal + if (a.y === y) { + const xDir = a.x < c.x ? -1 : 1; + const yDir = a.y < c.y ? 1 : -1; + return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`; + } + + const xDir = a.x < c.x ? 1 : -1; + const yDir = a.y < c.y ? -1 : 1; + return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`; } export function getSmoothStepPath({ @@ -43,76 +155,34 @@ export function getSmoothStepPath({ borderRadius = 5, centerX, centerY, + offset = 20, }: GetSmoothStepPathParams): string { - const [_centerX, _centerY, offsetX, offsetY] = getCenter({ sourceX, sourceY, targetX, targetY }); - const cornerWidth = Math.min(borderRadius, Math.abs(targetX - sourceX)); - const cornerHeight = Math.min(borderRadius, Math.abs(targetY - sourceY)); - const cornerSize = Math.min(cornerWidth, cornerHeight, offsetX, offsetY); - const leftAndRight = [Position.Left, Position.Right]; + const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY }); const cX = typeof centerX !== 'undefined' ? centerX : _centerX; const cY = typeof centerY !== 'undefined' ? centerY : _centerY; - let firstCornerPath = null; - let secondCornerPath = null; + const points = getPoints({ + source: { x: sourceX, y: sourceY }, + sourcePosition, + target: { x: targetX, y: targetY }, + targetPosition, + center: { x: cX, y: cY }, + offset, + }); - if (sourceX <= targetX) { - firstCornerPath = - sourceY <= targetY ? bottomLeftCorner(sourceX, cY, cornerSize) : topLeftCorner(sourceX, cY, cornerSize); - secondCornerPath = - sourceY <= targetY ? rightTopCorner(targetX, cY, cornerSize) : rightBottomCorner(targetX, cY, cornerSize); - } else { - firstCornerPath = - sourceY < targetY ? bottomRightCorner(sourceX, cY, cornerSize) : topRightCorner(sourceX, cY, cornerSize); - secondCornerPath = - sourceY < targetY ? leftTopCorner(targetX, cY, cornerSize) : leftBottomCorner(targetX, cY, cornerSize); - } + return points.reduce((res, p, i) => { + let segment = ''; - if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { - if (sourceX <= targetX) { - firstCornerPath = - sourceY <= targetY ? rightTopCorner(cX, sourceY, cornerSize) : rightBottomCorner(cX, sourceY, cornerSize); - secondCornerPath = - sourceY <= targetY ? bottomLeftCorner(cX, targetY, cornerSize) : topLeftCorner(cX, targetY, cornerSize); - } else if ( - (sourcePosition === Position.Right && targetPosition === Position.Left) || - (sourcePosition === Position.Left && targetPosition === Position.Right) || - (sourcePosition === Position.Left && targetPosition === Position.Left) - ) { - // and sourceX > targetX - firstCornerPath = - sourceY <= targetY ? leftTopCorner(cX, sourceY, cornerSize) : leftBottomCorner(cX, sourceY, cornerSize); - secondCornerPath = - sourceY <= targetY ? bottomRightCorner(cX, targetY, cornerSize) : topRightCorner(cX, targetY, cornerSize); - } - } else if (leftAndRight.includes(sourcePosition) && !leftAndRight.includes(targetPosition)) { - if (sourceX <= targetX) { - firstCornerPath = - sourceY <= targetY - ? rightTopCorner(targetX, sourceY, cornerSize) - : rightBottomCorner(targetX, sourceY, cornerSize); + if (i > 0 && i < points.length - 1) { + segment = getBend(points[i - 1], p, points[i + 1], borderRadius); } else { - firstCornerPath = - sourceY <= targetY - ? leftTopCorner(targetX, sourceY, cornerSize) - : leftBottomCorner(targetX, sourceY, cornerSize); + segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`; } - secondCornerPath = ''; - } else if (!leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { - if (sourceX <= targetX) { - firstCornerPath = - sourceY <= targetY - ? bottomLeftCorner(sourceX, targetY, cornerSize) - : topLeftCorner(sourceX, targetY, cornerSize); - } else { - firstCornerPath = - sourceY <= targetY - ? bottomRightCorner(sourceX, targetY, cornerSize) - : topRightCorner(sourceX, targetY, cornerSize); - } - secondCornerPath = ''; - } - return `M ${sourceX},${sourceY}${firstCornerPath}${secondCornerPath}L ${targetX},${targetY}`; + res += segment; + + return res; + }, ''); } const SmoothStepEdge = memo( @@ -132,8 +202,8 @@ const SmoothStepEdge = memo( targetPosition = Position.Top, markerEnd, markerStart, - borderRadius = 5, - }: EdgeSmoothStepProps) => { + options, + }: SmoothStepEdgeProps) => { const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }); const path = getSmoothStepPath({ @@ -143,7 +213,8 @@ const SmoothStepEdge = memo( targetX, targetY, targetPosition, - borderRadius, + borderRadius: options?.borderRadius, + offset: options?.offset, }); return ( diff --git a/packages/core/src/components/Edges/wrapEdge.tsx b/packages/core/src/components/Edges/wrapEdge.tsx index 909d46dc..f429f0bf 100644 --- a/packages/core/src/components/Edges/wrapEdge.tsx +++ b/packages/core/src/components/Edges/wrapEdge.tsx @@ -52,6 +52,7 @@ export default (EdgeComponent: ComponentType) => { rfId, ariaLabel, disableKeyboardA11y, + options, }: WrapEdgeProps): JSX.Element | null => { const edgeRef = useRef(null); const [updateHover, setUpdateHover] = useState(false); @@ -189,6 +190,7 @@ export default (EdgeComponent: ComponentType) => { targetHandleId={targetHandleId} markerStart={markerStartUrl} markerEnd={markerEndUrl} + options={options} /> )} diff --git a/packages/core/src/components/Nodes/wrapNode.tsx b/packages/core/src/components/Nodes/wrapNode.tsx index ee540e27..c1fdadb9 100644 --- a/packages/core/src/components/Nodes/wrapNode.tsx +++ b/packages/core/src/components/Nodes/wrapNode.tsx @@ -46,7 +46,6 @@ export default (NodeComponent: ComponentType) => { dragHandle, zIndex, isParent, - noPanClassName, noDragClassName, initialized, disableKeyboardA11y, diff --git a/packages/core/src/components/StoreUpdater/index.tsx b/packages/core/src/components/StoreUpdater/index.tsx index 533a34c7..f287a39d 100644 --- a/packages/core/src/components/StoreUpdater/index.tsx +++ b/packages/core/src/components/StoreUpdater/index.tsx @@ -126,7 +126,8 @@ const StoreUpdater = ({ const store = useStoreApi(); useEffect(() => { - setDefaultNodesAndEdges(defaultNodes, defaultEdges); + const edgesWithDefaults = defaultEdges?.map((e) => ({ ...e, ...defaultEdgeOptions })); + setDefaultNodesAndEdges(defaultNodes, edgesWithDefaults); return () => { reset(); diff --git a/packages/core/src/container/EdgeRenderer/index.tsx b/packages/core/src/container/EdgeRenderer/index.tsx index 4b51658b..590bda84 100644 --- a/packages/core/src/container/EdgeRenderer/index.tsx +++ b/packages/core/src/container/EdgeRenderer/index.tsx @@ -182,6 +182,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => { rfId={props.rfId} ariaLabel={edge.ariaLabel} disableKeyboardA11y={props.disableKeyboardA11y} + options={'options' in edge ? edge.options : undefined} /> ); })} diff --git a/packages/core/src/container/NodeRenderer/index.tsx b/packages/core/src/container/NodeRenderer/index.tsx index c9b4190f..762c367f 100644 --- a/packages/core/src/container/NodeRenderer/index.tsx +++ b/packages/core/src/container/NodeRenderer/index.tsx @@ -127,7 +127,6 @@ const NodeRenderer = (props: NodeRendererProps) => { zIndex={node[internalsSymbol]?.z ?? 0} isParent={!!node[internalsSymbol]?.isParent} noDragClassName={props.noDragClassName} - noPanClassName={props.noPanClassName} initialized={!!node.width && !!node.height} rfId={props.rfId} disableKeyboardA11y={props.disableKeyboardA11y} diff --git a/packages/core/src/container/ReactFlow/utils.ts b/packages/core/src/container/ReactFlow/utils.ts index 6eca2c89..b85e75d6 100644 --- a/packages/core/src/container/ReactFlow/utils.ts +++ b/packages/core/src/container/ReactFlow/utils.ts @@ -28,14 +28,3 @@ export function useNodeOrEdgeTypes(nodeOrEdgeTypes: any, createTypes: any): any return typesParsed; } - -export function injectStyle(css: string): void { - if (!css || typeof document === 'undefined') return; - - const head = document.head || document.getElementsByTagName('head')[0]; - const style = document.createElement('style'); - - head.appendChild(style); - - style.appendChild(document.createTextNode(css)); -} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 4777566e..6bbe82a5 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -14,6 +14,7 @@ export { getSimpleBezierCenter as getSimpleBezierEdgeCenter, } from './components/Edges/SimpleBezierEdge'; export { default as SmoothStepEdge, getSmoothStepPath } from './components/Edges/SmoothStepEdge'; +export { default as BaseEdge } from './components/Edges/BaseEdge'; export { internalsSymbol, rectToBox, boxToRect, getBoundsOfRects } from './utils'; export { diff --git a/packages/core/src/types/edges.ts b/packages/core/src/types/edges.ts index 16e98499..7e526459 100644 --- a/packages/core/src/types/edges.ts +++ b/packages/core/src/types/edges.ts @@ -6,7 +6,7 @@ import { Node } from './nodes'; import { Position } from './utils'; // interface for the user edge items -export interface Edge { +type DefaultEdge = { id: string; type?: string; source: string; @@ -32,7 +32,28 @@ export interface Edge { markerEnd?: EdgeMarkerType; zIndex?: number; ariaLabel?: string; -} +}; + +export type SmoothStepEdgeOptions = { + offset?: number; + borderRadius?: number; +}; + +type SmoothStepEdgeType = DefaultEdge & { + type: 'smoothstep'; + options?: SmoothStepEdgeOptions; +}; + +export type BezierEdgeOptions = { + curvature?: number; +}; + +type BezierEdgeType = DefaultEdge & { + type: 'default'; + options?: BezierEdgeOptions; +}; + +export type Edge = DefaultEdge | SmoothStepEdgeType | BezierEdgeType; export type DefaultEdgeOptions = Omit< Edge, @@ -64,7 +85,7 @@ export interface EdgeProps { targetHandleId?: string | null; markerStart?: string; markerEnd?: string; - curvature?: number; + options?: BezierEdgeOptions | SmoothStepEdgeOptions; } export type BaseEdgeProps = Pick< @@ -127,12 +148,16 @@ export interface WrapEdgeProps { rfId?: string; ariaLabel?: string | null; disableKeyboardA11y: boolean; + options?: SmoothStepEdgeOptions | BezierEdgeOptions; } -export interface EdgeSmoothStepProps extends EdgeProps { - borderRadius?: number; +export interface SmoothStepEdgeProps extends EdgeProps { + options?: SmoothStepEdgeOptions; } +export interface BezierEdgeProps extends EdgeProps { + options?: BezierEdgeOptions; +} export interface EdgeTextProps extends HTMLAttributes { x: number; y: number; diff --git a/packages/core/src/types/nodes.ts b/packages/core/src/types/nodes.ts index 5ba91cf4..af664647 100644 --- a/packages/core/src/types/nodes.ts +++ b/packages/core/src/types/nodes.ts @@ -89,7 +89,6 @@ export interface WrapNodeProps { dragHandle?: string; zIndex: number; isParent: boolean; - noPanClassName: string; noDragClassName: string; rfId: string; disableKeyboardA11y: boolean;