Merge branch 'main' of github.com:xyflow/xyflow
This commit is contained in:
7
.changeset/slow-snails-tickle.md
Normal file
7
.changeset/slow-snails-tickle.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@xyflow/react': patch
|
||||
'@xyflow/svelte': patch
|
||||
'@xyflow/system': patch
|
||||
---
|
||||
|
||||
Add stepPosition param to step edge
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ReactFlow, Node, Edge, Position, MarkerType } from '@xyflow/react';
|
||||
import { ReactFlow, Node, Position, MarkerType, BuiltInEdge } from '@xyflow/react';
|
||||
|
||||
const nodes: Node[] = [
|
||||
// LTR
|
||||
@@ -69,9 +69,107 @@ const nodes: Node[] = [
|
||||
targetPosition: Position.Bottom,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
// Bend Position Examples (horizontal)
|
||||
{
|
||||
id: '9',
|
||||
position: { x: 300, y: 0 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Right,
|
||||
targetPosition: Position.Right,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
position: { x: 600, y: 150 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Left,
|
||||
targetPosition: Position.Left,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
position: { x: 300, y: 300 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Right,
|
||||
targetPosition: Position.Right,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
position: { x: 600, y: 450 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Left,
|
||||
targetPosition: Position.Left,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
position: { x: 300, y: 600 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Right,
|
||||
targetPosition: Position.Right,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
position: { x: 600, y: 750 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Left,
|
||||
targetPosition: Position.Left,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
// Bend Position Examples (vertical)
|
||||
{
|
||||
id: '15',
|
||||
position: { x: 800, y: 0 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Bottom,
|
||||
targetPosition: Position.Bottom,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
position: { x: 950, y: 150 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Top,
|
||||
targetPosition: Position.Top,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
position: { x: 800, y: 300 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Bottom,
|
||||
targetPosition: Position.Bottom,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
position: { x: 950, y: 450 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Top,
|
||||
targetPosition: Position.Top,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
position: { x: 800, y: 600 },
|
||||
data: { label: 'Source' },
|
||||
sourcePosition: Position.Bottom,
|
||||
targetPosition: Position.Bottom,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
position: { x: 950, y: 750 },
|
||||
data: { label: 'Target' },
|
||||
sourcePosition: Position.Top,
|
||||
targetPosition: Position.Top,
|
||||
style: { background: 'rgba(255,255,255,0.5)' },
|
||||
},
|
||||
];
|
||||
|
||||
const edges: Edge[] = [
|
||||
const edges: BuiltInEdge[] = [
|
||||
{
|
||||
id: 'e1-2',
|
||||
source: '1',
|
||||
@@ -102,6 +200,69 @@ const edges: Edge[] = [
|
||||
source: '7',
|
||||
target: '8',
|
||||
},
|
||||
|
||||
// Bend Position Examples (horizontal)
|
||||
{
|
||||
id: 'e9-10',
|
||||
source: '9',
|
||||
target: '10',
|
||||
label: 'stepPosition: 0.2',
|
||||
pathOptions: {
|
||||
stepPosition: 0.2,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
{
|
||||
id: 'e11-12',
|
||||
source: '11',
|
||||
target: '12',
|
||||
label: 'stepPosition: 0.5 (default)',
|
||||
pathOptions: {
|
||||
stepPosition: 0.5,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
{
|
||||
id: 'e13-14',
|
||||
source: '13',
|
||||
target: '14',
|
||||
label: 'stepPosition: 0.8',
|
||||
pathOptions: {
|
||||
stepPosition: 0.8,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
// Bend Position Examples (vertical)
|
||||
{
|
||||
id: 'e15-16',
|
||||
source: '15',
|
||||
target: '16',
|
||||
label: 'stepPosition: 0.2',
|
||||
pathOptions: {
|
||||
stepPosition: 0.2,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
{
|
||||
id: 'e17-18',
|
||||
source: '17',
|
||||
target: '18',
|
||||
label: 'stepPosition: 0.5',
|
||||
pathOptions: {
|
||||
stepPosition: 0.5,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
{
|
||||
id: 'e19-20',
|
||||
source: '19',
|
||||
target: '20',
|
||||
label: 'stepPosition: 0.8',
|
||||
pathOptions: {
|
||||
stepPosition: 0.8,
|
||||
},
|
||||
interactionWidth: 0,
|
||||
},
|
||||
];
|
||||
|
||||
const defaultEdgeOptions = {
|
||||
@@ -115,8 +276,8 @@ const defaultEdgeOptions = {
|
||||
},
|
||||
};
|
||||
|
||||
const SimpleEdge = () => {
|
||||
function EdgeRouting() {
|
||||
return <ReactFlow defaultNodes={nodes} defaultEdges={edges} fitView defaultEdgeOptions={defaultEdgeOptions} />;
|
||||
};
|
||||
}
|
||||
|
||||
export default SimpleEdge;
|
||||
export default EdgeRouting;
|
||||
|
||||
@@ -36,6 +36,7 @@ function createSmoothStepEdge(params: { isInternal: boolean }) {
|
||||
targetPosition,
|
||||
borderRadius: pathOptions?.borderRadius,
|
||||
offset: pathOptions?.offset,
|
||||
stepPosition: pathOptions?.stepPosition,
|
||||
});
|
||||
|
||||
const _id = params.isInternal ? undefined : id;
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
sourcePosition,
|
||||
targetPosition,
|
||||
borderRadius: pathOptions?.borderRadius,
|
||||
offset: pathOptions?.offset
|
||||
offset: pathOptions?.offset,
|
||||
stepPosition: pathOptions?.stepPosition
|
||||
})
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -45,6 +45,7 @@ export type EdgeBase<
|
||||
export type SmoothStepPathOptions = {
|
||||
offset?: number;
|
||||
borderRadius?: number;
|
||||
stepPosition?: number;
|
||||
};
|
||||
|
||||
export type StepPathOptions = {
|
||||
|
||||
@@ -26,6 +26,12 @@ export interface GetSmoothStepPathParams {
|
||||
centerY?: number;
|
||||
/** @default 20 */
|
||||
offset?: number;
|
||||
/**
|
||||
* Controls where the bend occurs along the path.
|
||||
* 0 = at source, 1 = at target, 0.5 = midpoint
|
||||
* @default 0.5
|
||||
*/
|
||||
stepPosition?: number;
|
||||
}
|
||||
|
||||
const handleDirections = {
|
||||
@@ -63,6 +69,7 @@ function getPoints({
|
||||
targetPosition = Position.Top,
|
||||
center,
|
||||
offset,
|
||||
stepPosition,
|
||||
}: {
|
||||
source: XYPosition;
|
||||
sourcePosition: Position;
|
||||
@@ -70,6 +77,7 @@ function getPoints({
|
||||
targetPosition: Position;
|
||||
center: Partial<XYPosition>;
|
||||
offset: number;
|
||||
stepPosition: number;
|
||||
}): [XYPosition[], number, number, number, number] {
|
||||
const sourceDir = handleDirections[sourcePosition];
|
||||
const targetDir = handleDirections[targetPosition];
|
||||
@@ -88,7 +96,7 @@ function getPoints({
|
||||
const sourceGapOffset = { x: 0, y: 0 };
|
||||
const targetGapOffset = { x: 0, y: 0 };
|
||||
|
||||
const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
|
||||
const [, , defaultOffsetX, defaultOffsetY] = getEdgeCenter({
|
||||
sourceX: source.x,
|
||||
sourceY: source.y,
|
||||
targetX: target.x,
|
||||
@@ -97,8 +105,16 @@ function getPoints({
|
||||
|
||||
// opposite handle positions, default case
|
||||
if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
|
||||
centerX = center.x ?? defaultCenterX;
|
||||
centerY = center.y ?? defaultCenterY;
|
||||
if (dirAccessor === 'x') {
|
||||
// Primary direction is horizontal, so stepPosition affects X coordinate
|
||||
centerX = center.x ?? (sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition);
|
||||
centerY = center.y ?? (sourceGapped.y + targetGapped.y) / 2;
|
||||
} else {
|
||||
// Primary direction is vertical, so stepPosition affects Y coordinate
|
||||
centerX = center.x ?? (sourceGapped.x + targetGapped.x) / 2;
|
||||
centerY = center.y ?? (sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition);
|
||||
}
|
||||
|
||||
/*
|
||||
* --->
|
||||
* |
|
||||
@@ -252,6 +268,7 @@ export function getSmoothStepPath({
|
||||
centerX,
|
||||
centerY,
|
||||
offset = 20,
|
||||
stepPosition = 0.5,
|
||||
}: GetSmoothStepPathParams): [path: string, labelX: number, labelY: number, offsetX: number, offsetY: number] {
|
||||
const [points, labelX, labelY, offsetX, offsetY] = getPoints({
|
||||
source: { x: sourceX, y: sourceY },
|
||||
@@ -260,6 +277,7 @@ export function getSmoothStepPath({
|
||||
targetPosition,
|
||||
center: { x: centerX, y: centerY },
|
||||
offset,
|
||||
stepPosition,
|
||||
});
|
||||
|
||||
const path = points.reduce<string>((res, p, i) => {
|
||||
|
||||
Reference in New Issue
Block a user