@floegence/floe-webapp-core 0.85.1 → 0.86.1

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.
@@ -1,91 +1,94 @@
1
1
  import { applyGraphPositions as v } from "./positions.js";
2
- function $(i) {
3
- const n = /* @__PURE__ */ new Set(), p = (t) => {
4
- if (!t || n.has(t)) throw new Error(`Duplicate or empty graph ID: ${t}`);
5
- n.add(t);
6
- }, s = new Map(i.nodes.map((t) => [t.id, t]));
7
- for (const t of i.nodes) {
8
- if (p(t.id), ![t.width, t.height].every((r) => Number.isFinite(r) && r > 0))
9
- throw new Error(`Invalid dimensions for graph node: ${t.id}`);
10
- for (const r of t.ports ?? []) p(r.id);
11
- const a = /* @__PURE__ */ new Set([t.id]);
12
- let d = t.parentId;
2
+ import { computePackedGraphLayout as b } from "./packing.js";
3
+ function N(n) {
4
+ const o = /* @__PURE__ */ new Set(), c = (e) => {
5
+ if (!e || o.has(e)) throw new Error(`Duplicate or empty graph ID: ${e}`);
6
+ o.add(e);
7
+ }, a = new Map(n.nodes.map((e) => [e.id, e]));
8
+ for (const e of n.nodes) {
9
+ if (c(e.id), ![e.width, e.height].every((i) => Number.isFinite(i) && i > 0))
10
+ throw new Error(`Invalid dimensions for graph node: ${e.id}`);
11
+ for (const i of e.ports ?? []) c(i.id);
12
+ const s = /* @__PURE__ */ new Set([e.id]);
13
+ let d = e.parentId;
13
14
  for (; d !== void 0; ) {
14
- const r = s.get(d);
15
- if (!r || r.kind !== "group")
16
- throw new Error(`Invalid parent for graph node: ${t.id}`);
17
- if (a.has(d)) throw new Error(`Cyclic graph containment: ${t.id}`);
18
- a.add(d), d = r.parentId;
15
+ const i = a.get(d);
16
+ if (!i || i.kind !== "group")
17
+ throw new Error(`Invalid parent for graph node: ${e.id}`);
18
+ if (s.has(d)) throw new Error(`Cyclic graph containment: ${e.id}`);
19
+ s.add(d), d = i.parentId;
19
20
  }
20
21
  }
21
- for (const t of i.edges) {
22
- p(t.id);
23
- for (const [a, d] of [
24
- [t.source, t.sourcePort],
25
- [t.target, t.targetPort]
22
+ for (const e of n.edges) {
23
+ c(e.id);
24
+ for (const [s, d] of [
25
+ [e.source, e.sourcePort],
26
+ [e.target, e.targetPort]
26
27
  ]) {
27
- const r = s.get(a);
28
- if (!r || d !== void 0 && !r.ports?.some((c) => c.id === d))
29
- throw new Error(`Invalid endpoint for graph edge: ${t.id}`);
28
+ const i = a.get(s);
29
+ if (!i || d !== void 0 && !i.ports?.some((h) => h.id === d))
30
+ throw new Error(`Invalid endpoint for graph edge: ${e.id}`);
30
31
  }
31
32
  }
32
33
  }
33
- async function O(i, n, p) {
34
- $(i);
35
- const s = n.groupPadding ?? { top: 64, right: 28, bottom: 28, left: 28 };
36
- if (![...Object.values(s), n.spacing ?? 64].every((e) => Number.isFinite(e) && e >= 0))
34
+ async function P(n, o, c) {
35
+ if (N(n), o.aspectRatio !== void 0 && (!Number.isFinite(o.aspectRatio) || o.aspectRatio <= 0))
36
+ throw new Error("Graph layout aspect ratio must be finite and positive");
37
+ const a = o.groupPadding ?? { top: 64, right: 28, bottom: 28, left: 28 };
38
+ if (![...Object.values(a), o.spacing ?? 64].every((t) => Number.isFinite(t) && t >= 0))
37
39
  throw new Error("Graph layout spacing must be finite and nonnegative");
38
- const t = /* @__PURE__ */ new Map();
39
- for (const e of i.nodes)
40
- t.set(e.id, {
41
- id: e.id,
42
- width: e.width,
43
- height: e.height,
44
- ...e.kind === "group" ? { children: [] } : {},
45
- ports: e.ports?.map((o) => ({
46
- id: o.id,
40
+ if (o.aspectRatio !== void 0) return b(n, o, c);
41
+ const e = /* @__PURE__ */ new Map();
42
+ for (const t of n.nodes)
43
+ e.set(t.id, {
44
+ id: t.id,
45
+ width: t.width,
46
+ height: t.height,
47
+ ...t.kind === "group" ? { children: [] } : {},
48
+ ports: t.ports?.map((r) => ({
49
+ id: r.id,
47
50
  width: 1,
48
51
  height: 1,
49
- layoutOptions: { "elk.port.side": o.side }
52
+ layoutOptions: { "elk.port.side": r.side }
50
53
  })),
51
54
  layoutOptions: {
52
55
  "elk.portConstraints": "FIXED_ORDER",
53
- "elk.padding": `[top=${s.top},left=${s.left},bottom=${s.bottom},right=${s.right}]`
56
+ "elk.padding": `[top=${a.top},left=${a.left},bottom=${a.bottom},right=${a.right}]`
54
57
  }
55
58
  });
56
- const a = [];
57
- for (const e of i.nodes)
58
- (e.parentId ? t.get(e.parentId).children : a).push(t.get(e.id));
59
+ const s = [];
60
+ for (const t of n.nodes)
61
+ (t.parentId ? e.get(t.parentId).children : s).push(e.get(t.id));
59
62
  const d = /* @__PURE__ */ new Set([
60
- ...i.nodes.flatMap((e) => [e.id, ...(e.ports ?? []).map((o) => o.id)]),
61
- ...i.edges.map((e) => e.id)
63
+ ...n.nodes.flatMap((t) => [t.id, ...(t.ports ?? []).map((r) => r.id)]),
64
+ ...n.edges.map((t) => t.id)
62
65
  ]);
63
- let r = "$graph";
64
- for (; d.has(r); ) r += "$";
65
- const c = await p.layout({
66
- id: r,
67
- children: a,
68
- edges: i.edges.map((e) => ({
69
- id: e.id,
70
- sources: [e.sourcePort ?? e.source],
71
- targets: [e.targetPort ?? e.target]
66
+ let i = "$graph";
67
+ for (; d.has(i); ) i += "$";
68
+ const h = await c.layout({
69
+ id: i,
70
+ children: s,
71
+ edges: n.edges.map((t) => ({
72
+ id: t.id,
73
+ sources: [t.sourcePort ?? t.source],
74
+ targets: [t.targetPort ?? t.target]
72
75
  })),
73
76
  layoutOptions: {
74
77
  "elk.algorithm": "layered",
75
- "elk.direction": n.direction ?? "RIGHT",
78
+ "elk.direction": o.direction ?? "RIGHT",
76
79
  "elk.edgeRouting": "ORTHOGONAL",
77
80
  "elk.hierarchyHandling": "INCLUDE_CHILDREN",
78
- "elk.spacing.nodeNode": String(n.spacing ?? 64),
79
- "elk.layered.spacing.nodeNodeBetweenLayers": String(n.spacing ?? 64),
81
+ "elk.spacing.nodeNode": String(o.spacing ?? 64),
82
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(o.spacing ?? 64),
80
83
  "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES",
81
84
  "elk.randomSeed": "1"
82
85
  }
83
- }), f = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), I = (e) => {
84
- for (const o of e.edges ?? []) {
85
- const h = o.container ?? e.id, l = f.get(h) ?? { x: 0, y: 0 };
86
+ }), f = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), E = (t) => {
87
+ for (const r of t.edges ?? []) {
88
+ const p = r.container ?? t.id, l = f.get(p) ?? { x: 0, y: 0 };
86
89
  x.set(
87
- o.id,
88
- (o.sections ?? []).map(
90
+ r.id,
91
+ (r.sections ?? []).map(
89
92
  (g) => [g.startPoint, ...g.bendPoints ?? [], g.endPoint].map((w) => ({
90
93
  x: w.x + l.x,
91
94
  y: w.y + l.y
@@ -93,34 +96,34 @@ async function O(i, n, p) {
93
96
  )
94
97
  );
95
98
  }
96
- for (const o of e.children ?? []) I(o);
97
- }, E = (e, o, h) => {
98
- const l = o + (e.x ?? 0), g = h + (e.y ?? 0);
99
- f.set(e.id, { x: l, y: g, width: e.width ?? 0, height: e.height ?? 0 });
100
- for (const w of e.children ?? []) E(w, l, g);
99
+ for (const r of t.children ?? []) E(r);
100
+ }, I = (t, r, p) => {
101
+ const l = r + (t.x ?? 0), g = p + (t.y ?? 0);
102
+ f.set(t.id, { x: l, y: g, width: t.width ?? 0, height: t.height ?? 0 });
103
+ for (const w of t.children ?? []) I(w, l, g);
101
104
  };
102
- for (const e of c.children ?? []) E(e, 0, 0);
103
- I(c);
104
- const y = !n.positions?.length && n.anchor && f.get(n.anchor.nodeId), m = y ? n.anchor.position.x - y.x : 0, u = y ? n.anchor.position.y - y.y : 0, k = i.nodes.map((e) => {
105
- const o = f.get(e.id);
106
- return { ...e, ...o, x: o.x + m, y: o.y + u };
105
+ for (const t of h.children ?? []) I(t, 0, 0);
106
+ E(h);
107
+ const y = !o.positions?.length && o.anchor && f.get(o.anchor.nodeId), m = y ? o.anchor.position.x - y.x : 0, u = y ? o.anchor.position.y - y.y : 0, k = n.nodes.map((t) => {
108
+ const r = f.get(t.id);
109
+ return { ...t, ...r, x: r.x + m, y: r.y + u };
107
110
  });
108
111
  return v(
109
112
  {
110
113
  nodes: k,
111
- edges: i.edges.map((e) => ({
112
- ...e,
113
- sections: (x.get(e.id) ?? []).map(
114
- (o) => o.map((h) => ({ x: h.x + m, y: h.y + u }))
114
+ edges: n.edges.map((t) => ({
115
+ ...t,
116
+ sections: (x.get(t.id) ?? []).map(
117
+ (r) => r.map((p) => ({ x: p.x + m, y: p.y + u }))
115
118
  )
116
119
  })),
117
- bounds: { x: m, y: u, width: c.width ?? 0, height: c.height ?? 0 }
120
+ bounds: { x: m, y: u, width: h.width ?? 0, height: h.height ?? 0 }
118
121
  },
119
- n,
120
- i.nodes
122
+ o,
123
+ n.nodes
121
124
  );
122
125
  }
123
126
  export {
124
- O as computeGraphLayout,
125
- $ as validateGraphInput
127
+ P as computeGraphLayout,
128
+ N as validateGraphInput
126
129
  };
@@ -0,0 +1,4 @@
1
+ import type { ELK } from 'elkjs/lib/elk-api';
2
+ import type { GraphInput, GraphLayout, GraphLayoutOptions } from './types';
3
+ /** Lay out each containment level as peers, then route the complete compound graph. */
4
+ export declare function computePackedGraphLayout(input: GraphInput, options: GraphLayoutOptions, engine: Pick<ELK, 'layout'>): Promise<GraphLayout>;
@@ -0,0 +1,74 @@
1
+ import { applyGraphPositions as b, routeGraphGeometry as G } from "./positions.js";
2
+ async function O(d, n, k) {
3
+ const a = new Map(d.nodes.map((e) => [e.id, { ...e, x: 0, y: 0 }])), r = /* @__PURE__ */ new Map();
4
+ for (const e of a.values()) {
5
+ const i = r.get(e.parentId) ?? [];
6
+ i.push(e), r.set(e.parentId, i);
7
+ }
8
+ const x = /* @__PURE__ */ new Set([
9
+ ...d.nodes.flatMap((e) => [e.id, ...(e.ports ?? []).map((i) => i.id)]),
10
+ ...d.edges.map((e) => e.id)
11
+ ]);
12
+ let l = "$packed";
13
+ for (; x.has(l); ) l += "$";
14
+ const g = n.groupPadding ?? { top: 64, right: 28, bottom: 28, left: 28 }, p = (e, i, o) => {
15
+ e.x += i, e.y += o;
16
+ for (const c of r.get(e.id) ?? []) p(c, i, o);
17
+ }, y = (e, i) => {
18
+ let o = a.get(e);
19
+ for (; o && o.parentId !== i; )
20
+ o = o.parentId ? a.get(o.parentId) : void 0;
21
+ return o;
22
+ }, m = async (e) => {
23
+ const i = r.get(e) ?? [];
24
+ for (const t of i) {
25
+ if (!r.has(t.id)) continue;
26
+ const s = await m(t.id);
27
+ t.width = Math.max(t.width, s.width), t.height = Math.max(t.height, s.height);
28
+ }
29
+ if (!i.length) return { width: 0, height: 0 };
30
+ const o = /* @__PURE__ */ new Map();
31
+ for (const t of d.edges) {
32
+ const s = y(t.source, e), h = y(t.target, e);
33
+ if (!s || !h || s.id === h.id) continue;
34
+ const w = JSON.stringify([s.id, h.id]);
35
+ o.has(w) || o.set(w, { id: t.id, sources: [s.id], targets: [h.id] });
36
+ }
37
+ const c = await k.layout({
38
+ id: e ?? l,
39
+ children: i.map((t) => ({ id: t.id, width: t.width, height: t.height })),
40
+ edges: [...o.values()],
41
+ layoutOptions: {
42
+ "elk.algorithm": o.size ? "layered" : "rectpacking",
43
+ "elk.direction": n.direction ?? "RIGHT",
44
+ "elk.edgeRouting": "ORTHOGONAL",
45
+ "elk.separateConnectedComponents": "true",
46
+ "elk.aspectRatio": String(n.aspectRatio),
47
+ "elk.spacing.componentComponent": String(n.spacing ?? 64),
48
+ "elk.spacing.nodeNode": String(n.spacing ?? 64),
49
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(n.spacing ?? 64),
50
+ "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES",
51
+ "elk.padding": e ? `[top=${g.top},left=${g.left},bottom=${g.bottom},right=${g.right}]` : "[top=12,left=12,bottom=12,right=12]",
52
+ "elk.randomSeed": "1"
53
+ }
54
+ });
55
+ for (const t of c.children ?? []) {
56
+ const s = a.get(t.id);
57
+ p(s, (t.x ?? 0) - s.x, (t.y ?? 0) - s.y);
58
+ }
59
+ return { width: c.width ?? 0, height: c.height ?? 0 };
60
+ }, S = await m(), f = !n.positions?.length && n.anchor && a.get(n.anchor.nodeId);
61
+ if (f) {
62
+ const e = n.anchor.position.x - f.x, i = n.anchor.position.y - f.y;
63
+ for (const o of r.get(void 0) ?? []) p(o, e, i);
64
+ }
65
+ const u = {
66
+ nodes: [...a.values()],
67
+ edges: d.edges.map((e) => ({ ...e, sections: [] })),
68
+ bounds: { x: 0, y: 0, ...S }
69
+ };
70
+ return n.positions?.length ? b(u, n, d.nodes) : G(u);
71
+ }
72
+ export {
73
+ O as computePackedGraphLayout
74
+ };
@@ -1,3 +1,5 @@
1
1
  import type { GraphLayout, GraphLayoutOptions, GraphNode } from './types';
2
2
  /** Apply explicit fixed or preferred positions, then route the resulting geometry once. */
3
3
  export declare function applyGraphPositions(layout: GraphLayout, options: GraphLayoutOptions, input: readonly GraphNode[]): GraphLayout;
4
+ /** Shared routing and bounds for explicit positions and packed compound geometry. */
5
+ export declare function routeGraphGeometry(layout: GraphLayout): GraphLayout;
@@ -1,169 +1,174 @@
1
- const H = (e, n = 0) => ({
2
- left: e.x - n,
3
- top: e.y - n,
4
- right: e.x + e.width + n,
5
- bottom: e.y + e.height + n
6
- }), N = (e, n) => e.x > n.left && e.x < n.right && e.y > n.top && e.y < n.bottom, W = (e, n, v) => !v.some(
7
- (r) => e.x === n.x ? e.x > r.left && e.x < r.right && Math.max(e.y, n.y) > r.top && Math.min(e.y, n.y) < r.bottom : e.y > r.top && e.y < r.bottom && Math.max(e.x, n.x) > r.left && Math.min(e.x, n.x) < r.right
1
+ const T = (r, a = 0) => ({
2
+ left: r.x - a,
3
+ top: r.y - a,
4
+ right: r.x + r.width + a,
5
+ bottom: r.y + r.height + a
6
+ }), S = (r, a) => r.x > a.left && r.x < a.right && r.y > a.top && r.y < a.bottom, O = (r, a, w) => !w.some(
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
8
  );
9
- function A(e, n, v) {
10
- if (v.some((h) => N(e, h) || N(n, h)))
9
+ function P(r, a, w) {
10
+ if (w.some((e) => S(r, e) || S(a, e)))
11
11
  throw new Error("Pinned graph positions obstruct an edge endpoint");
12
- const r = [
13
- .../* @__PURE__ */ new Set([e.x, n.x, ...v.flatMap((h) => [h.left, h.right])])
14
- ].sort((h, t) => h - t), I = [
15
- .../* @__PURE__ */ new Set([e.y, n.y, ...v.flatMap((h) => [h.top, h.bottom])])
16
- ].sort((h, t) => h - t), w = (h) => ({ x: r[h % r.length], y: I[Math.floor(h / r.length)] }), M = I.indexOf(e.y) * r.length + r.indexOf(e.x), b = I.indexOf(n.y) * r.length + r.indexOf(n.x), S = /* @__PURE__ */ new Map([[M, 0]]), O = /* @__PURE__ */ new Map(), y = [], E = (h) => {
17
- let t = y.length;
18
- for (y.push(h); t > 0; ) {
19
- const c = t - 1 >> 1;
20
- if (y[c].score <= h.score) break;
21
- y[t] = y[c], t = c;
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
22
  }
23
- y[t] = h;
24
- }, T = () => {
25
- const h = y[0], t = y.pop();
26
- if (y.length) {
27
- let c = 0;
28
- for (; c * 2 + 1 < y.length; ) {
29
- let p = c * 2 + 1;
30
- if (p + 1 < y.length && y[p + 1].score < y[p].score && p++, y[p].score >= t.score) break;
31
- y[c] = y[p], c = p;
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
32
  }
33
- y[c] = t;
33
+ t[x] = i;
34
34
  }
35
- return h;
35
+ return e;
36
36
  };
37
- E({ id: M, score: 0, cost: 0 });
38
- let P = 0;
39
- for (; y.length && P++ < 5e4; ) {
40
- const h = T();
41
- if (h.cost !== S.get(h.id)) continue;
42
- if (h.id === b) {
43
- const x = [w(b)];
44
- let s = b;
45
- for (; s !== M; )
46
- s = O.get(s), x.push(w(s));
47
- return x.reverse(), x.filter((a, o) => {
48
- const f = x[o - 1], m = x[o + 1];
49
- return !f || !m || !(f.x === a.x && a.x === m.x || f.y === a.y && a.y === m.y);
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
50
  });
51
51
  }
52
- const t = w(h.id), c = h.id % r.length, p = Math.floor(h.id / r.length), d = [
53
- c ? h.id - 1 : -1,
54
- c + 1 < r.length ? h.id + 1 : -1,
55
- p ? h.id - r.length : -1,
56
- p + 1 < I.length ? h.id + r.length : -1
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
57
  ];
58
- for (const x of d) {
59
- if (x < 0) continue;
60
- const s = w(x), a = h.cost + Math.abs(t.x - s.x) + Math.abs(t.y - s.y);
61
- a >= (S.get(x) ?? 1 / 0) || !W(t, s, v) || (S.set(x, a), O.set(x, h.id), E({ id: x, cost: a, score: a + Math.abs(s.x - n.x) + Math.abs(s.y - n.y) }));
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
62
  }
63
63
  }
64
64
  throw new Error("Pinned graph positions cannot be routed within the layout budget");
65
65
  }
66
- function F(e, n, v) {
67
- if (!n.positions?.length) return e;
68
- const r = new Map(e.nodes.map((t) => [t.id, { ...t }])), I = /* @__PURE__ */ new Map();
69
- for (const t of n.positions) {
70
- if (!r.has(t.nodeId) || I.has(t.nodeId) || !Number.isFinite(t.x) || !Number.isFinite(t.y))
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))
71
71
  throw new Error(`Invalid graph position: ${t.nodeId}`);
72
- I.set(t.nodeId, t);
72
+ m.set(t.nodeId, t);
73
73
  }
74
- const w = /* @__PURE__ */ new Map();
75
- for (const t of r.values())
74
+ const l = /* @__PURE__ */ new Map();
75
+ for (const t of c.values())
76
76
  if (t.parentId) {
77
- const c = w.get(t.parentId) ?? [];
78
- c.push(t), w.set(t.parentId, c);
77
+ const u = l.get(t.parentId) ?? [];
78
+ u.push(t), l.set(t.parentId, u);
79
79
  }
80
- const M = n.groupPadding ?? { top: 64, left: 28, right: 28, bottom: 28 }, b = n.positionMode === "preferred", S = new Map(v.map((t) => [t.id, t])), O = (t, c, p) => {
81
- const d = { x: t.x, y: t.y }, x = I.get(t.id);
82
- t.x = x?.x ?? t.x + c, t.y = x?.y ?? t.y + p;
83
- const s = w.get(t.id) ?? [];
84
- for (const l of s) O(l, t.x - d.x, t.y - d.y);
85
- if (!s.length || b) return;
86
- const a = Math.min(...s.map((l) => l.x)) - M.left, o = Math.min(...s.map((l) => l.y)) - M.top;
87
- if (x && (a < t.x || o < t.y))
80
+ const g = a.groupPadding ?? { top: 64, left: 28, right: 28, bottom: 28 }, n = a.positionMode === "preferred", M = new Map(w.map((t) => [t.id, t])), d = (t, u, I) => {
81
+ const v = { x: t.x, y: t.y }, e = m.get(t.id);
82
+ t.x = e?.x ?? t.x + u, t.y = e?.y ?? t.y + I;
83
+ const i = l.get(t.id) ?? [];
84
+ for (const o of i) d(o, t.x - v.x, t.y - v.y);
85
+ if (!i.length || n) return;
86
+ const x = Math.min(...i.map((o) => o.x)) - g.left, h = Math.min(...i.map((o) => o.y)) - g.top;
87
+ if (e && (x < t.x || h < t.y))
88
88
  throw new Error(`Pinned child lies outside group content: ${t.id}`);
89
- const f = Math.max(
89
+ const s = Math.max(
90
90
  t.x + t.width,
91
- ...s.map((l) => l.x + l.width + M.right)
92
- ), m = Math.max(
91
+ ...i.map((o) => o.x + o.width + g.right)
92
+ ), y = Math.max(
93
93
  t.y + t.height,
94
- ...s.map((l) => l.y + l.height + M.bottom)
94
+ ...i.map((o) => o.y + o.height + g.bottom)
95
95
  );
96
- x || (t.x = Math.min(t.x, a), t.y = Math.min(t.y, o)), t.width = f - t.x, t.height = m - t.y;
96
+ e || (t.x = Math.min(t.x, x), t.y = Math.min(t.y, h)), t.width = s - t.x, t.height = y - t.y;
97
97
  };
98
- for (const t of r.values()) t.parentId || O(t, 0, 0);
99
- if (b) {
100
- const t = Math.max(16, n.spacing ?? 64), c = (s, a, o) => {
101
- s.x += a, s.y += o;
102
- for (const f of w.get(s.id) ?? []) c(f, a, o);
103
- }, p = (s) => {
104
- const a = [];
105
- for (const o of [...s].sort(
106
- (f, m) => f.y - m.y || f.x - m.x || f.id.localeCompare(m.id)
98
+ for (const t of c.values()) t.parentId || d(t, 0, 0);
99
+ if (n) {
100
+ const t = Math.max(16, a.spacing ?? 64), u = (i, x, h) => {
101
+ i.x += x, i.y += h;
102
+ for (const s of l.get(i.id) ?? []) u(s, x, h);
103
+ }, I = (i) => {
104
+ const x = [];
105
+ for (const h of [...i].sort(
106
+ (s, y) => s.y - y.y || s.x - y.x || s.id.localeCompare(y.id)
107
107
  )) {
108
- const f = { x: o.x, y: o.y };
109
- for (const i of [...a].sort((g, u) => g.x - u.x))
110
- o.y < i.y + i.height + t && o.y + o.height + t > i.y && f.x < i.x + i.width + t && f.x + o.width + t > i.x && (f.x = i.x + i.width + t);
111
- const m = { x: o.x, y: o.y };
112
- for (const i of [...a].sort((g, u) => g.y - u.y))
113
- o.x < i.x + i.width + t && o.x + o.width + t > i.x && m.y < i.y + i.height + t && m.y + o.height + t > i.y && (m.y = i.y + i.height + t);
114
- const l = f.x - o.x < m.y - o.y ? f : m;
115
- c(o, l.x - o.x, l.y - o.y), a.push(o);
108
+ const s = { x: h.x, y: h.y };
109
+ for (const p of [...x].sort((f, E) => f.x - E.x))
110
+ h.y < p.y + p.height + t && h.y + h.height + t > p.y && s.x < p.x + p.width + t && s.x + h.width + t > p.x && (s.x = p.x + p.width + t);
111
+ const y = { x: h.x, y: h.y };
112
+ for (const p of [...x].sort((f, E) => f.y - E.y))
113
+ h.x < p.x + p.width + t && h.x + h.width + t > p.x && y.y < p.y + p.height + t && y.y + h.height + t > p.y && (y.y = p.y + p.height + t);
114
+ const o = s.x - h.x < y.y - h.y ? s : y;
115
+ u(h, o.x - h.x, o.y - h.y), x.push(h);
116
116
  }
117
- }, d = (s) => {
118
- const a = w.get(s.id) ?? [];
119
- if (!a.length) return;
120
- for (const g of a) d(g);
121
- p(a);
122
- const o = Math.max(12, M.left), f = Math.max(12, M.top), m = Math.max(12, M.right), l = Math.max(12, M.bottom), i = I.get(s.id);
123
- s.x = Math.min(i?.x ?? 1 / 0, Math.min(...a.map((g) => g.x)) - o), s.y = Math.min(i?.y ?? 1 / 0, Math.min(...a.map((g) => g.y)) - f), s.width = Math.max(
124
- S.get(s.id).width,
125
- Math.max(...a.map((g) => g.x + g.width)) + m - s.x
126
- ), s.height = Math.max(
127
- S.get(s.id).height,
128
- Math.max(...a.map((g) => g.y + g.height)) + l - s.y
117
+ }, v = (i) => {
118
+ const x = l.get(i.id) ?? [];
119
+ if (!x.length) return;
120
+ for (const f of x) v(f);
121
+ I(x);
122
+ const h = Math.max(12, g.left), s = Math.max(12, g.top), y = Math.max(12, g.right), o = Math.max(12, g.bottom), p = m.get(i.id);
123
+ i.x = Math.min(p?.x ?? 1 / 0, Math.min(...x.map((f) => f.x)) - h), i.y = Math.min(p?.y ?? 1 / 0, Math.min(...x.map((f) => f.y)) - s), i.width = Math.max(
124
+ M.get(i.id).width,
125
+ Math.max(...x.map((f) => f.x + f.width)) + y - i.x
126
+ ), i.height = Math.max(
127
+ M.get(i.id).height,
128
+ Math.max(...x.map((f) => f.y + f.height)) + o - i.y
129
129
  );
130
- }, x = [...r.values()].filter((s) => !s.parentId);
131
- for (const s of x) d(s);
132
- p(x);
130
+ }, e = [...c.values()].filter((i) => !i.parentId);
131
+ for (const i of e) v(i);
132
+ I(e);
133
133
  }
134
- const y = e.edges.map((t) => {
135
- const c = r.get(t.source), p = r.get(t.target), d = (i, g, u) => i.ports?.find((k) => k.id === g)?.side ?? u, x = c.x + c.width / 2 <= p.x + p.width / 2, s = (i, g) => {
136
- const u = { x: i.x + i.width / 2, y: i.y + i.height / 2 };
137
- return g === "NORTH" ? [
138
- { x: u.x, y: i.y },
139
- { x: u.x, y: i.y - 8 }
140
- ] : g === "SOUTH" ? [
141
- { x: u.x, y: i.y + i.height },
142
- { x: u.x, y: i.y + i.height + 8 }
143
- ] : g === "WEST" ? [
144
- { x: i.x, y: u.y },
145
- { x: i.x - 8, y: u.y }
134
+ return N({ ...r, nodes: [...c.values()] });
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 }
146
150
  ] : [
147
- { x: i.x + i.width, y: u.y },
148
- { x: i.x + i.width + 8, y: u.y }
151
+ { x: s.x + s.width, y: o.y },
152
+ { x: s.x + s.width + 8, y: o.y }
149
153
  ];
150
- }, [a, o] = s(c, d(c, t.sourcePort, x ? "EAST" : "WEST")), [f, m] = s(
151
- p,
152
- d(p, t.targetPort, c === p ? "NORTH" : x ? "WEST" : "EAST")
153
- ), l = [...r.values()].filter((i) => i.kind !== "group").map((i) => H(i, 4));
154
- return { ...t, sections: [[a, ...A(o, m, l), f]] };
155
- }), E = [...r.values()], T = y.flatMap((t) => t.sections.flat()), P = Math.min(...E.map((t) => t.x), ...T.map((t) => t.x)), h = Math.min(...E.map((t) => t.y), ...T.map((t) => t.y));
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));
156
160
  return {
157
- nodes: E,
158
- edges: y,
161
+ nodes: c,
162
+ edges: w,
159
163
  bounds: {
160
- x: P,
161
- y: h,
162
- width: Math.max(...E.map((t) => t.x + t.width), ...T.map((t) => t.x)) - P,
163
- height: Math.max(...E.map((t) => t.y + t.height), ...T.map((t) => t.y)) - h
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
164
168
  }
165
169
  };
166
170
  }
167
171
  export {
168
- F as applyGraphPositions
172
+ k as applyGraphPositions,
173
+ N as routeGraphGeometry
169
174
  };