@statelyai/layout 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/elkjs/index.mjs +16 -12
- package/dist/index.mjs +2 -2
- package/dist/layered/index.mjs +1 -1
- package/dist/{layered-QwJn2gb2.mjs → layered-Bp8MkxWK.mjs} +361 -15
- package/dist/{spore-D15xIQKj.mjs → spore-ePWz2LtF.mjs} +1 -1
- package/package.json +5 -1
- package/src/elkjs/index.ts +25 -24
- package/src/layered/index.ts +488 -7
- package/src/layered/long-edges.ts +7 -6
- package/src/layered/strategies.ts +66 -6
|
@@ -30,6 +30,37 @@ function getOrientedEndpoints(
|
|
|
30
30
|
: [edge.sourceId, edge.targetId];
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
export function getOrientedPortDirection(
|
|
34
|
+
input: LayeredPhaseInput,
|
|
35
|
+
orientation: AcyclicOrientation,
|
|
36
|
+
node: GraphNode,
|
|
37
|
+
port: GraphPort,
|
|
38
|
+
): GraphPort["direction"] {
|
|
39
|
+
const configuredSide = input.portSettings?.(port, node)?.["port.side"];
|
|
40
|
+
if (
|
|
41
|
+
configuredSide !== "NORTH" &&
|
|
42
|
+
configuredSide !== "SOUTH" &&
|
|
43
|
+
configuredSide !== "WEST" &&
|
|
44
|
+
configuredSide !== "EAST"
|
|
45
|
+
) {
|
|
46
|
+
return port.direction;
|
|
47
|
+
}
|
|
48
|
+
let incoming = false;
|
|
49
|
+
let outgoing = false;
|
|
50
|
+
for (const edge of input.graph.edges) {
|
|
51
|
+
const reversed = orientation.reversedEdgeIds.has(edge.id);
|
|
52
|
+
if (edge.sourceId === node.id && edge.sourcePort === port.name) {
|
|
53
|
+
if (reversed) incoming = true;
|
|
54
|
+
else outgoing = true;
|
|
55
|
+
}
|
|
56
|
+
if (edge.targetId === node.id && edge.targetPort === port.name) {
|
|
57
|
+
if (reversed) outgoing = true;
|
|
58
|
+
else incoming = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return incoming && outgoing ? "inout" : outgoing ? "out" : incoming ? "in" : port.direction;
|
|
62
|
+
}
|
|
63
|
+
|
|
33
64
|
function cycleModelOrder(input: LayeredPhaseInput): Map<string, number> {
|
|
34
65
|
const enforced =
|
|
35
66
|
input.settings["considerModelOrder.groupModelOrder.cbGroupOrderStrategy"] === "ENFORCED";
|
|
@@ -4312,10 +4343,15 @@ function routeEdges(style: "ORTHOGONAL" | "POLYLINE" | "SPLINES"): EdgeRouter {
|
|
|
4312
4343
|
source.id === target.id &&
|
|
4313
4344
|
feedbackSourcePortSide !== undefined &&
|
|
4314
4345
|
feedbackSourcePortSide === feedbackTargetPortSide;
|
|
4346
|
+
const hasFixedPortSide = (node: GraphNode): boolean => {
|
|
4347
|
+
const constraints = String(input.nodeSettings?.(node)?.portConstraints ?? "UNDEFINED");
|
|
4348
|
+
return constraints !== "UNDEFINED" && constraints !== "FREE";
|
|
4349
|
+
};
|
|
4315
4350
|
const fixedSideFeedback =
|
|
4316
4351
|
style === "ORTHOGONAL" &&
|
|
4317
4352
|
!sameSideSelfLoop &&
|
|
4318
|
-
(feedbackSourcePortSide === sourceAwaySide ||
|
|
4353
|
+
((hasFixedPortSide(source) && feedbackSourcePortSide === sourceAwaySide) ||
|
|
4354
|
+
(hasFixedPortSide(target) && feedbackTargetPortSide === targetAwaySide));
|
|
4319
4355
|
if ((input.settings.feedbackEdges === true && reversedEdge) || fixedSideFeedback) {
|
|
4320
4356
|
if (fixedSideFeedback) outsideFeedbackEdgeIds.add(edge.id);
|
|
4321
4357
|
const crossSpacing = Number(input.settings["spacing.edgeNode"] ?? 10);
|
|
@@ -4769,12 +4805,32 @@ function routeEdges(style: "ORTHOGONAL" | "POLYLINE" | "SPLINES"): EdgeRouter {
|
|
|
4769
4805
|
(candidate) =>
|
|
4770
4806
|
candidate.targetId === edge.targetId && candidate.targetPort === edge.targetPort,
|
|
4771
4807
|
).length === 1;
|
|
4772
|
-
const
|
|
4808
|
+
const flexibleFeedback =
|
|
4809
|
+
reversedEdge && !hasFixedPortSide(source) && !hasFixedPortSide(target);
|
|
4810
|
+
const start = flexibleFeedback
|
|
4773
4811
|
? sourceFallback
|
|
4774
|
-
:
|
|
4775
|
-
|
|
4812
|
+
: sourceFixedSide
|
|
4813
|
+
? sourceFallback
|
|
4814
|
+
: getPortPoint(
|
|
4815
|
+
source,
|
|
4816
|
+
edge.sourcePort,
|
|
4817
|
+
sourceRect,
|
|
4818
|
+
sourceFallback,
|
|
4819
|
+
input.direction,
|
|
4820
|
+
input,
|
|
4821
|
+
);
|
|
4822
|
+
const end = flexibleFeedback
|
|
4776
4823
|
? targetFallback
|
|
4777
|
-
:
|
|
4824
|
+
: targetFixedSide
|
|
4825
|
+
? targetFallback
|
|
4826
|
+
: getPortPoint(
|
|
4827
|
+
target,
|
|
4828
|
+
edge.targetPort,
|
|
4829
|
+
targetRect,
|
|
4830
|
+
targetFallback,
|
|
4831
|
+
input.direction,
|
|
4832
|
+
input,
|
|
4833
|
+
);
|
|
4778
4834
|
const sourceLayer = flowLayerByNodeId.get(edge.sourceId) ?? 0;
|
|
4779
4835
|
const targetLayer = flowLayerByNodeId.get(edge.targetId) ?? 0;
|
|
4780
4836
|
const earlierLayer = Math.min(sourceLayer, targetLayer);
|
|
@@ -4955,6 +5011,7 @@ export function placePorts<P>(
|
|
|
4955
5011
|
direction: LayeredPhaseInput["direction"],
|
|
4956
5012
|
portSettings?: (port: GraphPort<P>) => ElkLayeredOptionValueByName | undefined,
|
|
4957
5013
|
nodeSettings?: ElkLayeredOptionValueByName,
|
|
5014
|
+
portDirection?: (port: GraphPort<P>) => GraphPort<P>["direction"],
|
|
4958
5015
|
): GraphPort<P>[] | undefined {
|
|
4959
5016
|
if (!ports) return undefined;
|
|
4960
5017
|
const horizontal = direction === "left" || direction === "right";
|
|
@@ -4981,7 +5038,7 @@ export function placePorts<P>(
|
|
|
4981
5038
|
sideByPort.set(port, configured);
|
|
4982
5039
|
continue;
|
|
4983
5040
|
}
|
|
4984
|
-
const outgoing = port.direction === "out";
|
|
5041
|
+
const outgoing = (portDirection?.(port) ?? port.direction) === "out";
|
|
4985
5042
|
const normalFarSide = reverse ? !outgoing : outgoing;
|
|
4986
5043
|
const farSide = sideFixed && configured === "UNDEFINED" ? !normalFarSide : normalFarSide;
|
|
4987
5044
|
sideByPort.set(port, horizontal ? (farSide ? "EAST" : "WEST") : farSide ? "SOUTH" : "NORTH");
|
|
@@ -5221,6 +5278,7 @@ export function normalizePlacementForPortExtents(
|
|
|
5221
5278
|
input: LayeredPhaseInput,
|
|
5222
5279
|
placement: NodePlacement,
|
|
5223
5280
|
order: LayerOrder,
|
|
5281
|
+
orientation: AcyclicOrientation,
|
|
5224
5282
|
): void {
|
|
5225
5283
|
const horizontal = input.direction === "left" || input.direction === "right";
|
|
5226
5284
|
const physicalLayers = order.layers
|
|
@@ -5267,6 +5325,7 @@ export function normalizePlacementForPortExtents(
|
|
|
5267
5325
|
input.direction,
|
|
5268
5326
|
(port) => input.portSettings?.(port, node),
|
|
5269
5327
|
{ ...input.settings, ...input.nodeSettings?.(node) },
|
|
5328
|
+
(port) => getOrientedPortDirection(input, orientation, node, port),
|
|
5270
5329
|
);
|
|
5271
5330
|
for (const port of ports ?? []) {
|
|
5272
5331
|
const extent = horizontal
|
|
@@ -5297,6 +5356,7 @@ export function normalizePlacementForPortExtents(
|
|
|
5297
5356
|
input.direction,
|
|
5298
5357
|
(port) => input.portSettings?.(port, node),
|
|
5299
5358
|
{ ...input.settings, ...input.nodeSettings?.(node) },
|
|
5359
|
+
(port) => getOrientedPortDirection(input, orientation, node, port),
|
|
5300
5360
|
);
|
|
5301
5361
|
for (const port of ports ?? []) {
|
|
5302
5362
|
minimumX = Math.min(minimumX, rect.x + (port.x ?? 0));
|