refactor(examples): switch examples from cra to nextjs
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import React, { FC } from 'react';
|
||||
import {
|
||||
getBezierPath,
|
||||
ConnectionLineComponentProps,
|
||||
Node,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import { getEdgeParams } from './utils';
|
||||
|
||||
const FloatingConnectionLine: FC<ConnectionLineComponentProps> = ({
|
||||
targetX,
|
||||
targetY,
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
sourceNode,
|
||||
}) => {
|
||||
if (!sourceNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const targetNode = {
|
||||
id: 'connection-target',
|
||||
width: 1,
|
||||
height: 1,
|
||||
position: { x: targetX, y: targetY },
|
||||
} as Node;
|
||||
|
||||
const { sx, sy } = getEdgeParams(sourceNode, targetNode);
|
||||
const d = getBezierPath({
|
||||
sourceX: sx,
|
||||
sourceY: sy,
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
targetX,
|
||||
targetY,
|
||||
});
|
||||
|
||||
return (
|
||||
<g>
|
||||
<path
|
||||
fill='none'
|
||||
stroke='#222'
|
||||
strokeWidth={1.5}
|
||||
className='animated'
|
||||
d={d}
|
||||
/>
|
||||
<circle
|
||||
cx={targetX}
|
||||
cy={targetY}
|
||||
fill='#fff'
|
||||
r={3}
|
||||
stroke='#222'
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export default FloatingConnectionLine;
|
||||
@@ -0,0 +1,55 @@
|
||||
import React, { FC, useMemo, CSSProperties } from 'react';
|
||||
import {
|
||||
EdgeProps,
|
||||
useStore,
|
||||
getBezierPath,
|
||||
ReactFlowState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import { getEdgeParams } from './utils';
|
||||
|
||||
const nodeSelector = (s: ReactFlowState) => s.nodeInternals;
|
||||
|
||||
const FloatingEdge: FC<EdgeProps> = ({ id, source, target, style }) => {
|
||||
const nodeInternals = useStore(nodeSelector);
|
||||
|
||||
const sourceNode = useMemo(
|
||||
() => nodeInternals.get(source),
|
||||
[source, nodeInternals]
|
||||
);
|
||||
const targetNode = useMemo(
|
||||
() => nodeInternals.get(target),
|
||||
[target, nodeInternals]
|
||||
);
|
||||
|
||||
if (!sourceNode || !targetNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(
|
||||
sourceNode,
|
||||
targetNode
|
||||
);
|
||||
|
||||
const d = getBezierPath({
|
||||
sourceX: sx,
|
||||
sourceY: sy,
|
||||
sourcePosition: sourcePos,
|
||||
targetPosition: targetPos,
|
||||
targetX: tx,
|
||||
targetY: ty,
|
||||
});
|
||||
|
||||
return (
|
||||
<g className='react-flow__connection'>
|
||||
<path
|
||||
id={id}
|
||||
className='react-flow__edge-path'
|
||||
d={d}
|
||||
style={style as CSSProperties}
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export default FloatingEdge;
|
||||
@@ -0,0 +1,54 @@
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
addEdge,
|
||||
Background,
|
||||
ReactFlowInstance,
|
||||
EdgeTypes,
|
||||
Connection,
|
||||
useNodesState,
|
||||
useEdgesState,
|
||||
} from '@react-flow/core';
|
||||
|
||||
import styles from './style.module.css';
|
||||
|
||||
import FloatingConnectionLine from './FloatingConnectionLine';
|
||||
import FloatingEdge from './FloatingEdge';
|
||||
import { createElements } from './utils';
|
||||
|
||||
const onInit = (reactFlowInstance: ReactFlowInstance) =>
|
||||
reactFlowInstance.fitView();
|
||||
|
||||
const { nodes: initialNodes, edges: initialEdges } =
|
||||
typeof window !== 'undefined' ? createElements() : { nodes: [], edges: [] };
|
||||
const edgeTypes: EdgeTypes = {
|
||||
floating: FloatingEdge,
|
||||
};
|
||||
|
||||
const FloatingEdges = () => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
|
||||
const onConnect = useCallback((connection: Connection) => {
|
||||
setEdges((eds) => addEdge(connection, eds));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.floatingedges}>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onConnect={onConnect}
|
||||
onInit={onInit}
|
||||
edgeTypes={edgeTypes}
|
||||
connectionLineComponent={FloatingConnectionLine}
|
||||
>
|
||||
<Background />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FloatingEdges;
|
||||
@@ -0,0 +1,9 @@
|
||||
.floatingedges {
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.floatingedges :global .react-flow__handle {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import React, { Position, XYPosition, Node, Edge } from '@react-flow/core';
|
||||
|
||||
// this helper function returns the intersection point
|
||||
// of the line between the center of the intersectionNode and the target node
|
||||
function getNodeIntersection(
|
||||
intersectionNode: Node,
|
||||
targetNode: Node
|
||||
): XYPosition {
|
||||
// https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a
|
||||
|
||||
const {
|
||||
width: intersectionNodeWidth,
|
||||
height: intersectionNodeHeight,
|
||||
position: intersectionNodePosition,
|
||||
} = intersectionNode;
|
||||
const targetPosition = targetNode.position;
|
||||
|
||||
const w = (intersectionNodeWidth ?? 0) / 2;
|
||||
const h = (intersectionNodeHeight ?? 0) / 2;
|
||||
|
||||
const x2 = intersectionNodePosition.x + w;
|
||||
const y2 = intersectionNodePosition.y + h;
|
||||
const x1 = targetPosition.x + w;
|
||||
const y1 = targetPosition.y + h;
|
||||
|
||||
const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h);
|
||||
const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h);
|
||||
const a = 1 / (Math.abs(xx1) + Math.abs(yy1));
|
||||
const xx3 = a * xx1;
|
||||
const yy3 = a * yy1;
|
||||
const x = w * (xx3 + yy3) + x2;
|
||||
const y = h * (-xx3 + yy3) + y2;
|
||||
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
// returns the position (top,right,bottom or right) passed node compared to the intersection point
|
||||
function getEdgePosition(node: Node, intersectionPoint: XYPosition) {
|
||||
const n = { ...node.position, ...node };
|
||||
const nx = Math.round(n.x);
|
||||
const ny = Math.round(n.y);
|
||||
const px = Math.round(intersectionPoint.x);
|
||||
const py = Math.round(intersectionPoint.y);
|
||||
|
||||
if (px <= nx + 1) {
|
||||
return Position.Left;
|
||||
}
|
||||
if (px >= nx + (n.width ?? 0) - 1) {
|
||||
return Position.Right;
|
||||
}
|
||||
if (py <= ny + 1) {
|
||||
return Position.Top;
|
||||
}
|
||||
if (py >= n.y + (n.height ?? 0) - 1) {
|
||||
return Position.Bottom;
|
||||
}
|
||||
|
||||
return Position.Top;
|
||||
}
|
||||
|
||||
// returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge
|
||||
export function getEdgeParams(source: Node, target: Node) {
|
||||
const sourceIntersectionPoint = getNodeIntersection(source, target);
|
||||
const targetIntersectionPoint = getNodeIntersection(target, source);
|
||||
|
||||
const sourcePos = getEdgePosition(source, sourceIntersectionPoint);
|
||||
const targetPos = getEdgePosition(target, targetIntersectionPoint);
|
||||
|
||||
return {
|
||||
sx: sourceIntersectionPoint.x,
|
||||
sy: sourceIntersectionPoint.y,
|
||||
tx: targetIntersectionPoint.x,
|
||||
ty: targetIntersectionPoint.y,
|
||||
sourcePos,
|
||||
targetPos,
|
||||
};
|
||||
}
|
||||
|
||||
type NodesAndEdges = {
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
};
|
||||
|
||||
export function createElements(): NodesAndEdges {
|
||||
const nodes: Node[] = [];
|
||||
const edges: Edge[] = [];
|
||||
|
||||
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
|
||||
|
||||
nodes.push({ id: 'target', data: { label: 'Target' }, position: center });
|
||||
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const degrees = i * (360 / 8);
|
||||
const radians = degrees * (Math.PI / 180);
|
||||
const x = 250 * Math.cos(radians) + center.x;
|
||||
const y = 250 * Math.sin(radians) + center.y;
|
||||
|
||||
nodes.push({ id: `${i}`, data: { label: 'Source' }, position: { x, y } });
|
||||
|
||||
edges.push({
|
||||
id: `edge-${i}`,
|
||||
target: 'target',
|
||||
source: `${i}`,
|
||||
type: 'floating',
|
||||
});
|
||||
}
|
||||
|
||||
return { nodes, edges };
|
||||
}
|
||||
Reference in New Issue
Block a user