@floegence/floe-webapp-core 0.86.7 → 0.86.8
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/dist/components/graph/layout.js +115 -85
- package/dist/components/graph/packing.js +141 -58
- package/dist/components/graph/positions.js +29 -29
- package/dist/components/graph/routing.js +163 -126
- package/dist/components/graph/types.d.ts +4 -2
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1,165 +1,202 @@
|
|
|
1
1
|
import { AvoidLib as H } from "../../node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/index.js";
|
|
2
|
-
import
|
|
3
|
-
let
|
|
4
|
-
const
|
|
5
|
-
async function
|
|
6
|
-
if (!
|
|
7
|
-
if (!
|
|
8
|
-
await (
|
|
9
|
-
throw
|
|
2
|
+
import W from "../../node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/libavoid.wasm.js";
|
|
3
|
+
let N;
|
|
4
|
+
const B = { NORTH: 1, SOUTH: 2, WEST: 4, EAST: 8 }, v = ["NORTH", "EAST", "SOUTH", "WEST"], m = (t) => t.delete();
|
|
5
|
+
async function F(t) {
|
|
6
|
+
if (!t.nodes.length) return t;
|
|
7
|
+
if (!t.edges.length) return C(t);
|
|
8
|
+
await (N ??= H.load(W).catch((h) => {
|
|
9
|
+
throw N = void 0, h;
|
|
10
10
|
}));
|
|
11
|
-
const
|
|
11
|
+
const e = H.getInstance(), s = new Map(t.nodes.map((h) => [h.id, h])), d = (h) => {
|
|
12
12
|
const y = [];
|
|
13
|
-
for (let
|
|
14
|
-
y.push(
|
|
13
|
+
for (let r = s.get(h).parentId; r; r = s.get(r).parentId)
|
|
14
|
+
y.push(r);
|
|
15
15
|
return y;
|
|
16
16
|
}, i = /* @__PURE__ */ new Map();
|
|
17
|
-
for (const
|
|
18
|
-
const y = /* @__PURE__ */ new Set([...
|
|
19
|
-
|
|
17
|
+
for (const h of t.edges) {
|
|
18
|
+
const y = /* @__PURE__ */ new Set([...d(h.source), ...d(h.target)]), r = JSON.stringify([...y].sort()), S = i.get(r) ?? { open: y, edges: [] };
|
|
19
|
+
S.edges.push(h), i.set(r, S);
|
|
20
20
|
}
|
|
21
|
-
const
|
|
22
|
-
for (const { open:
|
|
23
|
-
const
|
|
21
|
+
const f = /* @__PURE__ */ new Map();
|
|
22
|
+
for (const { open: h, edges: y } of i.values()) {
|
|
23
|
+
const r = new e.Router(2);
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
return m(
|
|
25
|
+
r.setRoutingParameter(e.RoutingParameter.shapeBufferDistance, 4), r.setRoutingParameter(e.RoutingParameter.idealNudgingDistance, 8), r.setRoutingParameter(e.RoutingParameter.crossingPenalty, 80), r.setRoutingParameter(e.RoutingParameter.fixedSharedPathPenalty, 120), r.setRoutingParameter(e.RoutingParameter.portDirectionPenalty, 0), r.setRoutingOption(e.RoutingOption.nudgeOrthogonalSegmentsConnectedToShapes, !1), r.setRoutingOption(e.RoutingOption.nudgeSharedPathsWithCommonEndPoint, !0);
|
|
26
|
+
const S = new Map(
|
|
27
|
+
t.nodes.filter((n) => !h.has(n.id) && d(n.id).every((a) => h.has(a))).map((n) => {
|
|
28
|
+
const a = new e.Point(n.x, n.y), p = new e.Point(n.x + n.width, n.y + n.height), o = new e.Rectangle(a, p), c = new e.ShapeRef(r, o);
|
|
29
|
+
return m(a), m(p), m(o), [n.id, c];
|
|
30
30
|
})
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
...f.flatMap(
|
|
50
|
-
(M) => Array.from(
|
|
51
|
-
{ length: c.length + 1 },
|
|
52
|
-
(T, R) => Math.max(p, Math.min(e - p, M + (R - c.length / 2) * 8))
|
|
53
|
-
)
|
|
54
|
-
)
|
|
55
|
-
])
|
|
56
|
-
];
|
|
57
|
-
}, u = o(
|
|
58
|
-
t.width,
|
|
59
|
-
c.map((e) => h(t.x, t.width, e.x, e.width) - t.x)
|
|
60
|
-
), w = o(
|
|
61
|
-
t.height,
|
|
62
|
-
c.map((e) => h(t.y, t.height, e.y, e.height) - t.y)
|
|
63
|
-
), l = (t.ports ?? []).map((e) => E(t, e.side)), P = y.some((e) => e.source === t.id && e.target === t.id), C = [
|
|
64
|
-
...l,
|
|
65
|
-
...P ? [
|
|
66
|
-
{ x: t.x + t.width, y: t.y + t.height / 3 },
|
|
67
|
-
{ x: t.x + t.width, y: t.y + t.height * 2 / 3 }
|
|
68
|
-
] : []
|
|
69
|
-
], b = (e, f, p, M, T) => {
|
|
70
|
-
const R = new n.ShapeConnectionPin(
|
|
71
|
-
r,
|
|
72
|
-
e,
|
|
73
|
-
f / t.width,
|
|
74
|
-
p / t.height,
|
|
31
|
+
), P = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map();
|
|
32
|
+
y.forEach((n) => {
|
|
33
|
+
const a = s.get(n.source), p = s.get(n.target), o = D(a, p), c = n.sourcePort ? a.ports.find((u) => u.id === n.sourcePort).side : n.targetPort ? O(p.ports.find((u) => u.id === n.targetPort).side) : o.source, g = n.targetPort ? p.ports.find((u) => u.id === n.targetPort).side : n.sourcePort ? O(a.ports.find((u) => u.id === n.sourcePort).side) : o.target, w = [n.source, n.target].sort().join("\0"), x = R.get(w) ?? 0;
|
|
34
|
+
R.set(w, x + 1), P.set(n.id, {
|
|
35
|
+
sourceSide: c,
|
|
36
|
+
targetSide: g,
|
|
37
|
+
offset: x % 2 === 0 ? -6 : 6
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
for (const n of t.nodes) {
|
|
41
|
+
const a = S.get(n.id);
|
|
42
|
+
if (!a) continue;
|
|
43
|
+
const p = (o, c, g, w, x) => {
|
|
44
|
+
const u = new e.ShapeConnectionPin(
|
|
45
|
+
a,
|
|
46
|
+
o,
|
|
47
|
+
c / n.width,
|
|
48
|
+
g / n.height,
|
|
75
49
|
!0,
|
|
76
50
|
0,
|
|
77
|
-
|
|
51
|
+
w
|
|
78
52
|
);
|
|
79
|
-
|
|
80
|
-
|
|
53
|
+
u.setExclusive(x), u.setConnectionCost(
|
|
54
|
+
n.width / 2 + n.height / 2 - Math.abs(c - n.width / 2) - Math.abs(g - n.height / 2)
|
|
81
55
|
);
|
|
82
|
-
}, d = (e, f, p) => {
|
|
83
|
-
C.some((M) => M.x === t.x + e && M.y === t.y + f) || b(1, e, f, p, !0);
|
|
84
56
|
};
|
|
85
|
-
for (const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
d(0, e, 4), d(t.width, e, 8);
|
|
89
|
-
for (const e of new Set(t.ports?.map((f) => f.side))) {
|
|
90
|
-
const { x: f, y: p } = E(t, e);
|
|
91
|
-
b(v.indexOf(e) + 2, f - t.x, p - t.y, F[e], !1);
|
|
57
|
+
for (const o of new Set(n.ports?.map((c) => c.side))) {
|
|
58
|
+
const { x: c, y: g } = A(n, o);
|
|
59
|
+
p(v.indexOf(o) + 2, c - n.x, g - n.y, B[o], !1);
|
|
92
60
|
}
|
|
93
|
-
P && (b(6, t.width, t.height / 3, 8, !1), b(7, t.width, t.height * 2 / 3, 8, !1));
|
|
94
61
|
}
|
|
95
|
-
const
|
|
96
|
-
const o =
|
|
97
|
-
if (
|
|
98
|
-
return new
|
|
99
|
-
|
|
100
|
-
|
|
62
|
+
const l = (n, a, p) => {
|
|
63
|
+
const o = s.get(n), c = S.get(n);
|
|
64
|
+
if (c && a)
|
|
65
|
+
return new e.ConnEnd(
|
|
66
|
+
c,
|
|
67
|
+
v.indexOf(o.ports.find((u) => u.id === a).side) + 2
|
|
101
68
|
);
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
69
|
+
const g = a ? A(o, o.ports.find((u) => u.id === a).side) : p, w = new e.Point(g.x, g.y), x = new e.ConnEnd(w);
|
|
70
|
+
return m(w), x;
|
|
71
|
+
}, M = y.map((n) => {
|
|
72
|
+
const a = s.get(n.source), p = s.get(n.target), o = P.get(n.id), c = l(
|
|
73
|
+
n.source,
|
|
74
|
+
n.sourcePort,
|
|
75
|
+
n.source === n.target ? { x: a.x + a.width, y: a.y + a.height / 3 } : k(a, o.sourceSide, p, o.offset)
|
|
76
|
+
), g = l(
|
|
77
|
+
n.target,
|
|
78
|
+
n.targetPort,
|
|
79
|
+
n.source === n.target ? {
|
|
80
|
+
x: p.x + p.width,
|
|
81
|
+
y: p.y + p.height * 2 / 3
|
|
82
|
+
} : k(p, o.targetSide, a, o.offset)
|
|
83
|
+
), w = new e.ConnRef(r, c, g);
|
|
84
|
+
if (m(c), m(g), n.source === n.target) {
|
|
85
|
+
const x = s.get(n.source), u = new e.CheckpointVector();
|
|
86
|
+
for (const U of [x.y + x.height / 3, x.y + x.height * 2 / 3]) {
|
|
87
|
+
const E = new e.Point(x.x + x.width + 24, U), b = new e.Checkpoint(E);
|
|
88
|
+
u.push_back(b), m(E), m(b);
|
|
113
89
|
}
|
|
114
|
-
|
|
90
|
+
w.setRoutingCheckpoints(u), m(u);
|
|
115
91
|
}
|
|
116
|
-
return { edge:
|
|
92
|
+
return { edge: n, connection: w };
|
|
117
93
|
});
|
|
118
|
-
|
|
119
|
-
for (const { edge:
|
|
120
|
-
const
|
|
121
|
-
const w =
|
|
122
|
-
return m(w),
|
|
94
|
+
r.processTransaction();
|
|
95
|
+
for (const { edge: n, connection: a } of M) {
|
|
96
|
+
const p = a.displayRoute(), o = Array.from({ length: p.size() }, (c, g) => {
|
|
97
|
+
const w = p.at(g), x = { x: w.x, y: w.y };
|
|
98
|
+
return m(w), x;
|
|
123
99
|
});
|
|
124
|
-
if (m(
|
|
125
|
-
throw new Error(`Graph edge cannot be routed: ${
|
|
126
|
-
|
|
100
|
+
if (m(p), !a.hasValidRoute() || o.length < 2 || o.some((c) => !Number.isFinite(c.x) || !Number.isFinite(c.y)) || o.some((c, g) => g > 0 && c.x !== o[g - 1].x && c.y !== o[g - 1].y))
|
|
101
|
+
throw new Error(`Graph edge cannot be routed: ${n.id}`);
|
|
102
|
+
f.set(n.id, o);
|
|
127
103
|
}
|
|
128
104
|
} finally {
|
|
129
|
-
|
|
105
|
+
r.delete();
|
|
130
106
|
}
|
|
131
107
|
}
|
|
132
|
-
const
|
|
133
|
-
return
|
|
108
|
+
const T = t.edges.map((h) => ({ ...h, sections: [f.get(h.id)] }));
|
|
109
|
+
return C({
|
|
110
|
+
nodes: t.nodes,
|
|
111
|
+
edges: T,
|
|
112
|
+
bounds: t.bounds
|
|
113
|
+
});
|
|
134
114
|
}
|
|
135
|
-
function
|
|
136
|
-
const
|
|
137
|
-
...
|
|
115
|
+
function C(t) {
|
|
116
|
+
const e = [
|
|
117
|
+
...t.nodes.flatMap((i) => [
|
|
138
118
|
{ x: i.x, y: i.y },
|
|
139
119
|
{ x: i.x + i.width, y: i.y + i.height }
|
|
140
120
|
]),
|
|
141
|
-
...
|
|
142
|
-
],
|
|
121
|
+
...t.edges.flatMap((i) => i.sections.flat())
|
|
122
|
+
], s = Math.min(...e.map((i) => i.x)), d = Math.min(...e.map((i) => i.y));
|
|
143
123
|
return {
|
|
144
|
-
nodes:
|
|
145
|
-
edges:
|
|
124
|
+
nodes: t.nodes,
|
|
125
|
+
edges: t.edges,
|
|
146
126
|
bounds: {
|
|
147
|
-
x,
|
|
148
|
-
y:
|
|
149
|
-
width: Math.max(...
|
|
150
|
-
height: Math.max(...
|
|
127
|
+
x: s,
|
|
128
|
+
y: d,
|
|
129
|
+
width: Math.max(...e.map((i) => i.x)) - s,
|
|
130
|
+
height: Math.max(...e.map((i) => i.y)) - d
|
|
151
131
|
}
|
|
152
132
|
};
|
|
153
133
|
}
|
|
154
|
-
function
|
|
134
|
+
function A(t, e) {
|
|
155
135
|
return {
|
|
156
|
-
x:
|
|
157
|
-
y:
|
|
136
|
+
x: e === "WEST" ? t.x : e === "EAST" ? t.x + t.width : t.x + t.width / 2,
|
|
137
|
+
y: e === "NORTH" ? t.y : e === "SOUTH" ? t.y + t.height : t.y + t.height / 2
|
|
158
138
|
};
|
|
159
139
|
}
|
|
160
|
-
function
|
|
161
|
-
return
|
|
140
|
+
function O(t) {
|
|
141
|
+
return {
|
|
142
|
+
NORTH: "SOUTH",
|
|
143
|
+
EAST: "WEST",
|
|
144
|
+
SOUTH: "NORTH",
|
|
145
|
+
WEST: "EAST"
|
|
146
|
+
}[t];
|
|
147
|
+
}
|
|
148
|
+
function D(t, e) {
|
|
149
|
+
const s = e.x + e.width / 2 - (t.x + t.width / 2), d = e.y + e.height / 2 - (t.y + t.height / 2), i = Math.max(t.x - (e.x + e.width), e.x - (t.x + t.width), 0), f = Math.max(
|
|
150
|
+
t.y - (e.y + e.height),
|
|
151
|
+
e.y - (t.y + t.height),
|
|
152
|
+
0
|
|
153
|
+
), h = (f === 0 && i > 0 ? !0 : i === 0 && f > 0 ? !1 : i === 0 && f === 0 ? Math.abs(s) >= Math.abs(d) : i <= f) ? s >= 0 ? "EAST" : "WEST" : d >= 0 ? "SOUTH" : "NORTH";
|
|
154
|
+
return { source: h, target: O(h) };
|
|
155
|
+
}
|
|
156
|
+
function k(t, e, s, d = 0) {
|
|
157
|
+
const i = (r) => Math.min(8, r / 4), f = (r, S, P) => Math.max(S + i(P), Math.min(S + P - i(P), r)), T = (r, S, P, R) => {
|
|
158
|
+
const l = Math.max(r, P), M = Math.min(r + S, P + R);
|
|
159
|
+
return l < M ? (l + M) / 2 + d : void 0;
|
|
160
|
+
}, h = s.x + s.width / 2, y = s.y + s.height / 2;
|
|
161
|
+
switch (e) {
|
|
162
|
+
case "NORTH":
|
|
163
|
+
return {
|
|
164
|
+
x: f(
|
|
165
|
+
T(t.x, t.width, s.x, s.width) ?? h + d,
|
|
166
|
+
t.x,
|
|
167
|
+
t.width
|
|
168
|
+
),
|
|
169
|
+
y: t.y
|
|
170
|
+
};
|
|
171
|
+
case "EAST":
|
|
172
|
+
return {
|
|
173
|
+
x: t.x + t.width,
|
|
174
|
+
y: f(
|
|
175
|
+
T(t.y, t.height, s.y, s.height) ?? y + d,
|
|
176
|
+
t.y,
|
|
177
|
+
t.height
|
|
178
|
+
)
|
|
179
|
+
};
|
|
180
|
+
case "SOUTH":
|
|
181
|
+
return {
|
|
182
|
+
x: f(
|
|
183
|
+
T(t.x, t.width, s.x, s.width) ?? h + d,
|
|
184
|
+
t.x,
|
|
185
|
+
t.width
|
|
186
|
+
),
|
|
187
|
+
y: t.y + t.height
|
|
188
|
+
};
|
|
189
|
+
case "WEST":
|
|
190
|
+
return {
|
|
191
|
+
x: t.x,
|
|
192
|
+
y: f(
|
|
193
|
+
T(t.y, t.height, s.y, s.height) ?? y + d,
|
|
194
|
+
t.y,
|
|
195
|
+
t.height
|
|
196
|
+
)
|
|
197
|
+
};
|
|
198
|
+
}
|
|
162
199
|
}
|
|
163
200
|
export {
|
|
164
|
-
|
|
201
|
+
F as routeGraphGeometry
|
|
165
202
|
};
|
|
@@ -52,8 +52,10 @@ export interface GraphLayoutOptions {
|
|
|
52
52
|
positions?: readonly (GraphPoint & {
|
|
53
53
|
nodeId: string;
|
|
54
54
|
})[];
|
|
55
|
-
/**
|
|
56
|
-
|
|
55
|
+
/** Root-level ranks. Unassigned roots are placed deterministically near their closest ranked neighbors. */
|
|
56
|
+
layers?: readonly (readonly string[])[];
|
|
57
|
+
/** Fixed (default) rejects impossible geometry. Preferred retains positions; compact uses them only as stable ordering hints. */
|
|
58
|
+
positionMode?: 'fixed' | 'preferred' | 'compact';
|
|
57
59
|
direction?: 'RIGHT' | 'DOWN' | 'LEFT' | 'UP';
|
|
58
60
|
spacing?: number;
|
|
59
61
|
groupPadding?: {
|