@floegence/floe-webapp-core 0.86.5 → 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 -57
- package/dist/components/graph/positions.d.ts +2 -3
- package/dist/components/graph/positions.js +55 -154
- package/dist/components/graph/routing.d.ts +3 -0
- package/dist/components/graph/routing.js +202 -0
- package/dist/components/graph/types.d.ts +4 -2
- package/dist/libavoid.wasm +0 -0
- package/dist/licenses/graph-notice.txt +11 -0
- package/dist/licenses/libavoid-sources.tar.gz +0 -0
- package/dist/licenses/libavoid.txt +505 -0
- package/dist/node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/index.js +1005 -0
- package/dist/node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/libavoid.wasm.js +4 -0
- package/dist/styles.css +1 -1
- package/package.json +2 -1
|
@@ -1,174 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
(c) => r.x === a.x ? r.x > c.left && r.x < c.right && Math.max(r.y, a.y) > c.top && Math.min(r.y, a.y) < c.bottom : r.y > c.top && r.y < c.bottom && Math.max(r.x, a.x) > c.left && Math.min(r.x, a.x) < c.right
|
|
8
|
-
);
|
|
9
|
-
function P(r, a, w) {
|
|
10
|
-
if (w.some((e) => S(r, e) || S(a, e)))
|
|
11
|
-
throw new Error("Pinned graph positions obstruct an edge endpoint");
|
|
12
|
-
const c = [
|
|
13
|
-
.../* @__PURE__ */ new Set([r.x, a.x, ...w.flatMap((e) => [e.left, e.right])])
|
|
14
|
-
].sort((e, i) => e - i), m = [
|
|
15
|
-
.../* @__PURE__ */ new Set([r.y, a.y, ...w.flatMap((e) => [e.top, e.bottom])])
|
|
16
|
-
].sort((e, i) => e - i), l = (e) => ({ x: c[e % c.length], y: m[Math.floor(e / c.length)] }), g = m.indexOf(r.y) * c.length + c.indexOf(r.x), n = m.indexOf(a.y) * c.length + c.indexOf(a.x), M = /* @__PURE__ */ new Map([[g, 0]]), d = /* @__PURE__ */ new Map(), t = [], u = (e) => {
|
|
17
|
-
let i = t.length;
|
|
18
|
-
for (t.push(e); i > 0; ) {
|
|
19
|
-
const x = i - 1 >> 1;
|
|
20
|
-
if (t[x].score <= e.score) break;
|
|
21
|
-
t[i] = t[x], i = x;
|
|
22
|
-
}
|
|
23
|
-
t[i] = e;
|
|
24
|
-
}, I = () => {
|
|
25
|
-
const e = t[0], i = t.pop();
|
|
26
|
-
if (t.length) {
|
|
27
|
-
let x = 0;
|
|
28
|
-
for (; x * 2 + 1 < t.length; ) {
|
|
29
|
-
let h = x * 2 + 1;
|
|
30
|
-
if (h + 1 < t.length && t[h + 1].score < t[h].score && h++, t[h].score >= i.score) break;
|
|
31
|
-
t[x] = t[h], x = h;
|
|
32
|
-
}
|
|
33
|
-
t[x] = i;
|
|
34
|
-
}
|
|
35
|
-
return e;
|
|
36
|
-
};
|
|
37
|
-
u({ id: g, score: 0, cost: 0 });
|
|
38
|
-
let v = 0;
|
|
39
|
-
for (; t.length && v++ < 5e4; ) {
|
|
40
|
-
const e = I();
|
|
41
|
-
if (e.cost !== M.get(e.id)) continue;
|
|
42
|
-
if (e.id === n) {
|
|
43
|
-
const y = [l(n)];
|
|
44
|
-
let o = n;
|
|
45
|
-
for (; o !== g; )
|
|
46
|
-
o = d.get(o), y.push(l(o));
|
|
47
|
-
return y.reverse(), y.filter((p, f) => {
|
|
48
|
-
const E = y[f - 1], b = y[f + 1];
|
|
49
|
-
return !E || !b || !(E.x === p.x && p.x === b.x || E.y === p.y && p.y === b.y);
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
const i = l(e.id), x = e.id % c.length, h = Math.floor(e.id / c.length), s = [
|
|
53
|
-
x ? e.id - 1 : -1,
|
|
54
|
-
x + 1 < c.length ? e.id + 1 : -1,
|
|
55
|
-
h ? e.id - c.length : -1,
|
|
56
|
-
h + 1 < m.length ? e.id + c.length : -1
|
|
57
|
-
];
|
|
58
|
-
for (const y of s) {
|
|
59
|
-
if (y < 0) continue;
|
|
60
|
-
const o = l(y), p = e.cost + Math.abs(i.x - o.x) + Math.abs(i.y - o.y);
|
|
61
|
-
p >= (M.get(y) ?? 1 / 0) || !O(i, o, w) || (M.set(y, p), d.set(y, e.id), u({ id: y, cost: p, score: p + Math.abs(o.x - a.x) + Math.abs(o.y - a.y) }));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
throw new Error("Pinned graph positions cannot be routed within the layout budget");
|
|
65
|
-
}
|
|
66
|
-
function k(r, a, w) {
|
|
67
|
-
if (!a.positions?.length) return r;
|
|
68
|
-
const c = new Map(r.nodes.map((t) => [t.id, { ...t }])), m = /* @__PURE__ */ new Map();
|
|
69
|
-
for (const t of a.positions) {
|
|
70
|
-
if (!c.has(t.nodeId) || m.has(t.nodeId) || !Number.isFinite(t.x) || !Number.isFinite(t.y))
|
|
1
|
+
import { routeGraphGeometry as G } from "./routing.js";
|
|
2
|
+
function E(d, p, v) {
|
|
3
|
+
if (!p.positions?.length || p.positionMode === "compact") return d;
|
|
4
|
+
const f = new Map(d.nodes.map((t) => [t.id, { ...t }])), l = /* @__PURE__ */ new Map();
|
|
5
|
+
for (const t of p.positions) {
|
|
6
|
+
if (!f.has(t.nodeId) || l.has(t.nodeId) || !Number.isFinite(t.x) || !Number.isFinite(t.y))
|
|
71
7
|
throw new Error(`Invalid graph position: ${t.nodeId}`);
|
|
72
|
-
|
|
8
|
+
l.set(t.nodeId, t);
|
|
73
9
|
}
|
|
74
|
-
const
|
|
75
|
-
for (const t of
|
|
10
|
+
const y = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const t of f.values())
|
|
76
12
|
if (t.parentId) {
|
|
77
|
-
const
|
|
78
|
-
|
|
13
|
+
const m = y.get(t.parentId) ?? [];
|
|
14
|
+
m.push(t), y.set(t.parentId, m);
|
|
79
15
|
}
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
t.x =
|
|
83
|
-
const i =
|
|
84
|
-
for (const
|
|
85
|
-
if (!i.length ||
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
16
|
+
const x = p.groupPadding ?? { top: 64, left: 28, right: 28, bottom: 28 }, u = p.positionMode === "preferred", I = new Map(v.map((t) => [t.id, t])), b = (t, m, M) => {
|
|
17
|
+
const g = { x: t.x, y: t.y }, c = l.get(t.id);
|
|
18
|
+
t.x = c?.x ?? t.x + m, t.y = c?.y ?? t.y + M;
|
|
19
|
+
const i = y.get(t.id) ?? [];
|
|
20
|
+
for (const a of i) b(a, t.x - g.x, t.y - g.y);
|
|
21
|
+
if (!i.length || u) return;
|
|
22
|
+
const r = Math.min(...i.map((a) => a.x)) - x.left, h = Math.min(...i.map((a) => a.y)) - x.top;
|
|
23
|
+
if (c && (r < t.x || h < t.y))
|
|
88
24
|
throw new Error(`Pinned child lies outside group content: ${t.id}`);
|
|
89
25
|
const s = Math.max(
|
|
90
26
|
t.x + t.width,
|
|
91
|
-
...i.map((
|
|
92
|
-
),
|
|
27
|
+
...i.map((a) => a.x + a.width + x.right)
|
|
28
|
+
), n = Math.max(
|
|
93
29
|
t.y + t.height,
|
|
94
|
-
...i.map((
|
|
30
|
+
...i.map((a) => a.y + a.height + x.bottom)
|
|
95
31
|
);
|
|
96
|
-
|
|
32
|
+
c || (t.x = Math.min(t.x, r), t.y = Math.min(t.y, h)), t.width = s - t.x, t.height = n - t.y;
|
|
97
33
|
};
|
|
98
|
-
for (const t of
|
|
99
|
-
if (
|
|
100
|
-
const t = Math.max(16,
|
|
101
|
-
i.x +=
|
|
102
|
-
for (const s of
|
|
103
|
-
},
|
|
104
|
-
const
|
|
34
|
+
for (const t of f.values()) t.parentId || b(t, 0, 0);
|
|
35
|
+
if (u) {
|
|
36
|
+
const t = Math.max(16, p.spacing ?? 64), m = (i, r, h) => {
|
|
37
|
+
i.x += r, i.y += h;
|
|
38
|
+
for (const s of y.get(i.id) ?? []) m(s, r, h);
|
|
39
|
+
}, M = (i) => {
|
|
40
|
+
const r = [];
|
|
105
41
|
for (const h of [...i].sort(
|
|
106
|
-
(s,
|
|
42
|
+
(s, n) => s.y - n.y || s.x - n.x || s.id.localeCompare(n.id)
|
|
107
43
|
)) {
|
|
108
44
|
const s = { x: h.x, y: h.y };
|
|
109
|
-
for (const
|
|
110
|
-
h.y <
|
|
111
|
-
const
|
|
112
|
-
for (const
|
|
113
|
-
h.x <
|
|
114
|
-
const
|
|
115
|
-
|
|
45
|
+
for (const o of [...r].sort((e, w) => e.x - w.x))
|
|
46
|
+
h.y < o.y + o.height + t && h.y + h.height + t > o.y && s.x < o.x + o.width + t && s.x + h.width + t > o.x && (s.x = o.x + o.width + t);
|
|
47
|
+
const n = { x: h.x, y: h.y };
|
|
48
|
+
for (const o of [...r].sort((e, w) => e.y - w.y))
|
|
49
|
+
h.x < o.x + o.width + t && h.x + h.width + t > o.x && n.y < o.y + o.height + t && n.y + h.height + t > o.y && (n.y = o.y + o.height + t);
|
|
50
|
+
const a = s.x - h.x < n.y - h.y ? s : n;
|
|
51
|
+
m(h, a.x - h.x, a.y - h.y), r.push(h);
|
|
116
52
|
}
|
|
117
|
-
},
|
|
118
|
-
const
|
|
119
|
-
if (!
|
|
120
|
-
for (const
|
|
121
|
-
|
|
122
|
-
const h = Math.max(12,
|
|
123
|
-
i.x = Math.min(
|
|
124
|
-
|
|
125
|
-
Math.max(...
|
|
53
|
+
}, g = (i) => {
|
|
54
|
+
const r = y.get(i.id) ?? [];
|
|
55
|
+
if (!r.length) return;
|
|
56
|
+
for (const e of r) g(e);
|
|
57
|
+
M(r);
|
|
58
|
+
const h = Math.max(12, x.left), s = Math.max(12, x.top), n = Math.max(12, x.right), a = Math.max(12, x.bottom), o = l.get(i.id);
|
|
59
|
+
i.x = Math.min(o?.x ?? 1 / 0, Math.min(...r.map((e) => e.x)) - h), i.y = Math.min(o?.y ?? 1 / 0, Math.min(...r.map((e) => e.y)) - s), i.width = Math.max(
|
|
60
|
+
I.get(i.id).width,
|
|
61
|
+
Math.max(...r.map((e) => e.x + e.width)) + n - i.x
|
|
126
62
|
), i.height = Math.max(
|
|
127
|
-
|
|
128
|
-
Math.max(...
|
|
63
|
+
I.get(i.id).height,
|
|
64
|
+
Math.max(...r.map((e) => e.y + e.height)) + a - i.y
|
|
129
65
|
);
|
|
130
|
-
},
|
|
131
|
-
for (const i of
|
|
132
|
-
|
|
66
|
+
}, c = [...f.values()].filter((i) => !i.parentId);
|
|
67
|
+
for (const i of c) g(i);
|
|
68
|
+
M(c);
|
|
133
69
|
}
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
function N(r) {
|
|
137
|
-
if (!r.nodes.length) return r;
|
|
138
|
-
const a = new Map(r.nodes.map((n) => [n.id, n])), w = r.edges.map((n) => {
|
|
139
|
-
const M = a.get(n.source), d = a.get(n.target), t = (s, y, o) => s.ports?.find((p) => p.id === y)?.side ?? o, u = M.x + M.width / 2 <= d.x + d.width / 2, I = (s, y) => {
|
|
140
|
-
const o = { x: s.x + s.width / 2, y: s.y + s.height / 2 };
|
|
141
|
-
return y === "NORTH" ? [
|
|
142
|
-
{ x: o.x, y: s.y },
|
|
143
|
-
{ x: o.x, y: s.y - 8 }
|
|
144
|
-
] : y === "SOUTH" ? [
|
|
145
|
-
{ x: o.x, y: s.y + s.height },
|
|
146
|
-
{ x: o.x, y: s.y + s.height + 8 }
|
|
147
|
-
] : y === "WEST" ? [
|
|
148
|
-
{ x: s.x, y: o.y },
|
|
149
|
-
{ x: s.x - 8, y: o.y }
|
|
150
|
-
] : [
|
|
151
|
-
{ x: s.x + s.width, y: o.y },
|
|
152
|
-
{ x: s.x + s.width + 8, y: o.y }
|
|
153
|
-
];
|
|
154
|
-
}, [v, e] = I(M, t(M, n.sourcePort, u ? "EAST" : "WEST")), [i, x] = I(
|
|
155
|
-
d,
|
|
156
|
-
t(d, n.targetPort, M === d ? "NORTH" : u ? "WEST" : "EAST")
|
|
157
|
-
), h = [...a.values()].filter((s) => s.kind !== "group").map((s) => T(s, 4));
|
|
158
|
-
return { ...n, sections: [[v, ...P(e, x, h), i]] };
|
|
159
|
-
}), c = [...a.values()], m = w.flatMap((n) => n.sections.flat()), l = Math.min(...c.map((n) => n.x), ...m.map((n) => n.x)), g = Math.min(...c.map((n) => n.y), ...m.map((n) => n.y));
|
|
160
|
-
return {
|
|
161
|
-
nodes: c,
|
|
162
|
-
edges: w,
|
|
163
|
-
bounds: {
|
|
164
|
-
x: l,
|
|
165
|
-
y: g,
|
|
166
|
-
width: Math.max(...c.map((n) => n.x + n.width), ...m.map((n) => n.x)) - l,
|
|
167
|
-
height: Math.max(...c.map((n) => n.y + n.height), ...m.map((n) => n.y)) - g
|
|
168
|
-
}
|
|
169
|
-
};
|
|
70
|
+
return G({ ...d, nodes: [...f.values()] });
|
|
170
71
|
}
|
|
171
72
|
export {
|
|
172
|
-
|
|
173
|
-
|
|
73
|
+
E as applyGraphPositions,
|
|
74
|
+
G as routeGraphGeometry
|
|
174
75
|
};
|
|
@@ -0,0 +1,202 @@
|
|
|
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 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
|
+
}));
|
|
11
|
+
const e = H.getInstance(), s = new Map(t.nodes.map((h) => [h.id, h])), d = (h) => {
|
|
12
|
+
const y = [];
|
|
13
|
+
for (let r = s.get(h).parentId; r; r = s.get(r).parentId)
|
|
14
|
+
y.push(r);
|
|
15
|
+
return y;
|
|
16
|
+
}, i = /* @__PURE__ */ new Map();
|
|
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
|
+
}
|
|
21
|
+
const f = /* @__PURE__ */ new Map();
|
|
22
|
+
for (const { open: h, edges: y } of i.values()) {
|
|
23
|
+
const r = new e.Router(2);
|
|
24
|
+
try {
|
|
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
|
+
})
|
|
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,
|
|
49
|
+
!0,
|
|
50
|
+
0,
|
|
51
|
+
w
|
|
52
|
+
);
|
|
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)
|
|
55
|
+
);
|
|
56
|
+
};
|
|
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);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
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
|
|
68
|
+
);
|
|
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);
|
|
89
|
+
}
|
|
90
|
+
w.setRoutingCheckpoints(u), m(u);
|
|
91
|
+
}
|
|
92
|
+
return { edge: n, connection: w };
|
|
93
|
+
});
|
|
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;
|
|
99
|
+
});
|
|
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);
|
|
103
|
+
}
|
|
104
|
+
} finally {
|
|
105
|
+
r.delete();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
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
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function C(t) {
|
|
116
|
+
const e = [
|
|
117
|
+
...t.nodes.flatMap((i) => [
|
|
118
|
+
{ x: i.x, y: i.y },
|
|
119
|
+
{ x: i.x + i.width, y: i.y + i.height }
|
|
120
|
+
]),
|
|
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));
|
|
123
|
+
return {
|
|
124
|
+
nodes: t.nodes,
|
|
125
|
+
edges: t.edges,
|
|
126
|
+
bounds: {
|
|
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
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function A(t, e) {
|
|
135
|
+
return {
|
|
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
|
|
138
|
+
};
|
|
139
|
+
}
|
|
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
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
F as routeGraphGeometry
|
|
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?: {
|
|
Binary file
|
|
@@ -3,3 +3,14 @@ Copyright (c) 2017 Kiel University and others.
|
|
|
3
3
|
Licensed under the Eclipse Public License 2.0. A copy is in elkjs.txt.
|
|
4
4
|
Unmodified upstream source is available at https://github.com/kieler/elkjs/tree/0.12.0
|
|
5
5
|
and https://registry.npmjs.org/elkjs/-/elkjs-0.12.0.tgz.
|
|
6
|
+
|
|
7
|
+
Orthogonal routing uses libavoid-js 0.5.0-beta.5 and its separate unmodified
|
|
8
|
+
libavoid.wasm library. libavoid is Copyright (C) Monash University and others;
|
|
9
|
+
libavoid-js is maintained by Vladyslav Hnatiuk. Licensed under LGPL-2.1-or-later;
|
|
10
|
+
a copy is in libavoid.txt. Corresponding source and build instructions are
|
|
11
|
+
included in libavoid-sources.tar.gz. The unmodified source revisions are:
|
|
12
|
+
https://github.com/Aksem/libavoid-js/tree/5062a42fbd82fff562afeebcbb7b1ed45eed8e75
|
|
13
|
+
https://github.com/Aksem/adaptagrams/tree/0ab3467b4ed3523bb3e404a0dd7da7647d9eb13d
|
|
14
|
+
The separate WASM library can be replaced with an API-compatible build.
|
|
15
|
+
Extract the source archive, enter libavoid-js, and run python3 tools/generate.py
|
|
16
|
+
(requires Docker), npm install, and npm run build to rebuild the library.
|
|
Binary file
|