@floegence/floe-webapp-core 0.86.15 → 0.86.16
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/assets/layout-worker-BK6m515B.js +1879 -0
- package/dist/components/graph/GraphCanvas.d.ts +4 -0
- package/dist/components/graph/GraphCanvas.js +153 -95
- package/dist/components/graph/GraphMinimap.d.ts +14 -0
- package/dist/components/graph/GraphMinimap.js +88 -0
- package/dist/components/graph/engine.js +29 -19
- package/dist/components/graph/layout-worker.d.ts +1 -0
- package/dist/graph.css +66 -0
- package/dist/graph.d.ts +1 -0
- package/dist/graph.js +7 -5
- package/package.json +1 -1
- package/dist/_virtual/_commonjs-dynamic-modules.js +0 -6
- package/dist/_virtual/_commonjsHelpers.js +0 -6
- package/dist/_virtual/elk-api.js +0 -7
- package/dist/_virtual/elk-api2.js +0 -4
- package/dist/components/graph/layout.js +0 -160
- package/dist/components/graph/packing.js +0 -158
- package/dist/components/graph/positions.js +0 -76
- package/dist/components/graph/routing.js +0 -280
- package/dist/node_modules/.pnpm/elkjs@0.12.0/node_modules/elkjs/lib/elk-api.js +0 -186
- package/dist/node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/index.js +0 -1005
- package/dist/node_modules/.pnpm/libavoid-js@0.5.0-beta.5/node_modules/libavoid-js/dist/libavoid.wasm.js +0 -4
|
@@ -21,6 +21,10 @@ export interface GraphCanvasProps {
|
|
|
21
21
|
onInteractionStart?: () => void;
|
|
22
22
|
/** Overlay content should use shared SurfaceFloatingLayer for point placement. */
|
|
23
23
|
overlay?: JSX.Element;
|
|
24
|
+
/** Optional interactive overview. Its geometry follows the same visible layout. */
|
|
25
|
+
minimap?: {
|
|
26
|
+
ariaLabel: string;
|
|
27
|
+
};
|
|
24
28
|
class?: string;
|
|
25
29
|
}
|
|
26
30
|
/** Controlled graph surface. Hosts own documents and selection; Floe owns geometry and input. */
|
|
@@ -1,79 +1,111 @@
|
|
|
1
|
-
import { insert as
|
|
2
|
-
import { createUniqueId as
|
|
3
|
-
import { InfiniteCanvas as
|
|
4
|
-
import { resolveSurfaceInteractionTargetRole as
|
|
5
|
-
import { graphRelatedEdges as
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { insert as w, createComponent as x, setAttribute as l, effect as S, className as K, template as I, memo as ae, setStyleProperty as T, use as ie, delegateEvents as oe } from "solid-js/web";
|
|
2
|
+
import { createUniqueId as le, createSignal as O, createMemo as y, onMount as ce, For as j, Show as D, onCleanup as de } from "solid-js";
|
|
3
|
+
import { InfiniteCanvas as ue } from "../ui/InfiniteCanvas.js";
|
|
4
|
+
import { resolveSurfaceInteractionTargetRole as se } from "../ui/localInteractionSurface.js";
|
|
5
|
+
import { graphRelatedEdges as U, graphEdgeLabelPosition as he, graphSectionPath as ge } from "./geometry.js";
|
|
6
|
+
import { GraphMinimap as fe } from "./GraphMinimap.js";
|
|
7
|
+
var ve = /* @__PURE__ */ I("<div data-floe-canvas-pan-surface=true role=group tabindex=0>"), me = /* @__PURE__ */ I("<div role=region tabindex=0>"), be = /* @__PURE__ */ I('<svg class=floe-graph__edges width=1 height=1><defs><marker viewBox="0 0 8 8"refX=7 refY=4 markerWidth=7 markerHeight=7 orient=auto-start-reverse><path d="M1 1 L7 4 L1 7"fill=none stroke=context-stroke stroke-width=1.2>'), xe = /* @__PURE__ */ I("<svg><g><path class=floe-graph__edge></path><path class=floe-graph__edge-target tabindex=0 role=button data-floe-canvas-pan-surface=true></svg>", !1, !0, !1), ye = /* @__PURE__ */ I("<svg><text class=floe-graph__edge-label aria-hidden=true></svg>", !1, !0, !1);
|
|
8
|
+
function Le(i) {
|
|
9
|
+
const H = `graph-arrow-${le()}`;
|
|
9
10
|
let g;
|
|
10
|
-
const [
|
|
11
|
+
const [J, Q] = O(null), [V, Z] = O({
|
|
11
12
|
width: 0,
|
|
12
13
|
height: 0
|
|
13
|
-
}), X = () => i.highlight === void 0 ?
|
|
14
|
+
}), X = () => i.highlight === void 0 ? J() : i.highlight, p = y(() => new Map(i.layout.nodes.map((e) => [e.id, e]))), ee = y(() => {
|
|
14
15
|
const e = X();
|
|
15
|
-
return e?.kind === "node" ?
|
|
16
|
-
}), Y =
|
|
16
|
+
return e?.kind === "node" ? U(i.layout, e.id) : new Set(e ? [e.id] : []);
|
|
17
|
+
}), Y = y(() => {
|
|
17
18
|
const e = X();
|
|
18
19
|
if (e?.kind !== "node") return null;
|
|
19
|
-
const t =
|
|
20
|
-
return
|
|
21
|
-
}), A = (e) => i.selected?.kind === e.kind && i.selected.id === e.id,
|
|
20
|
+
const t = p().get(e.id), n = t?.kind === "group" ? t.id : t?.parentId;
|
|
21
|
+
return n ? U(i.layout, n) : null;
|
|
22
|
+
}), A = (e) => i.selected?.kind === e.kind && i.selected.id === e.id, B = (e) => {
|
|
22
23
|
const {
|
|
23
24
|
width: t,
|
|
24
|
-
height:
|
|
25
|
-
} =
|
|
26
|
-
if (!t || !
|
|
27
|
-
const
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
height: n
|
|
26
|
+
} = V();
|
|
27
|
+
if (!t || !n) return;
|
|
28
|
+
const r = -e.x / e.scale - 240, a = -e.y / e.scale - 240, m = r + t / e.scale + 480, c = a + n / e.scale + 480;
|
|
29
|
+
return {
|
|
30
|
+
left: r,
|
|
31
|
+
top: a,
|
|
32
|
+
right: m,
|
|
33
|
+
bottom: c
|
|
34
|
+
};
|
|
35
|
+
}, te = (e) => {
|
|
36
|
+
const t = B(e);
|
|
37
|
+
if (!t) return i.layout.nodes;
|
|
38
|
+
const {
|
|
39
|
+
left: n,
|
|
40
|
+
top: r,
|
|
41
|
+
right: a,
|
|
42
|
+
bottom: m
|
|
43
|
+
} = t;
|
|
44
|
+
return i.layout.nodes.filter((c) => c.id === i.selected?.id || c.x + c.width >= n && c.x <= a && c.y + c.height >= r && c.y <= m);
|
|
45
|
+
}, N = y(() => i.layout.edges.map((e) => ({
|
|
46
|
+
edge: e,
|
|
47
|
+
path: e.sections.map(ge).join(" "),
|
|
48
|
+
label: he(e.sections),
|
|
49
|
+
segments: e.sections.flatMap((t) => t.slice(1).map((n, r) => ({
|
|
50
|
+
left: Math.min(n.x, t[r].x),
|
|
51
|
+
right: Math.max(n.x, t[r].x),
|
|
52
|
+
top: Math.min(n.y, t[r].y),
|
|
53
|
+
bottom: Math.max(n.y, t[r].y)
|
|
54
|
+
})))
|
|
55
|
+
}))), ne = (e) => {
|
|
56
|
+
const t = B(e);
|
|
57
|
+
return t ? N().filter(({
|
|
58
|
+
edge: n,
|
|
59
|
+
segments: r
|
|
60
|
+
}) => n.id === i.selected?.id || r.some((a) => a.left <= t.right && a.right >= t.left && a.top <= t.bottom && a.bottom >= t.top)) : N();
|
|
61
|
+
}, f = (e) => {
|
|
62
|
+
Q(e), i.onHover?.(e);
|
|
63
|
+
}, k = (e, t, n) => {
|
|
64
|
+
const r = t.getBoundingClientRect();
|
|
33
65
|
return {
|
|
34
66
|
object: e,
|
|
35
67
|
owner: t,
|
|
36
|
-
position:
|
|
37
|
-
x:
|
|
38
|
-
y:
|
|
68
|
+
position: n && (n.clientX !== 0 || n.clientY !== 0) ? {
|
|
69
|
+
x: n.clientX,
|
|
70
|
+
y: n.clientY
|
|
39
71
|
} : {
|
|
40
|
-
x:
|
|
41
|
-
y:
|
|
72
|
+
x: r.left + r.width / 2,
|
|
73
|
+
y: r.top + Math.min(32, r.height / 2)
|
|
42
74
|
}
|
|
43
75
|
};
|
|
44
|
-
},
|
|
45
|
-
i.onContextMenu && (t.preventDefault(), t.stopPropagation(), i.onContextMenu(
|
|
46
|
-
},
|
|
47
|
-
t.target === t.currentTarget && (t.key === "ContextMenu" || t.shiftKey && t.key === "F10" ? (t.preventDefault(), t.stopPropagation(), i.onContextMenu?.(
|
|
76
|
+
}, z = (e, t) => {
|
|
77
|
+
i.onContextMenu && (t.preventDefault(), t.stopPropagation(), i.onContextMenu(k(e, t.currentTarget, t)));
|
|
78
|
+
}, G = (e, t) => {
|
|
79
|
+
t.target === t.currentTarget && (t.key === "ContextMenu" || t.shiftKey && t.key === "F10" ? (t.preventDefault(), t.stopPropagation(), i.onContextMenu?.(k(e, t.currentTarget))) : t.key === "Enter" ? (t.preventDefault(), t.stopPropagation(), i.onActivate?.(k(e, t.currentTarget))) : t.key === "Escape" && (f(null), i.onActivate?.(k(null, g))));
|
|
48
80
|
};
|
|
49
|
-
|
|
81
|
+
ce(() => {
|
|
50
82
|
if (!g) return;
|
|
51
|
-
const e = () =>
|
|
83
|
+
const e = () => Z({
|
|
52
84
|
width: g.clientWidth,
|
|
53
85
|
height: g.clientHeight
|
|
54
86
|
});
|
|
55
87
|
e();
|
|
56
88
|
const t = new ResizeObserver(e);
|
|
57
|
-
t.observe(g),
|
|
89
|
+
t.observe(g), de(() => t.disconnect());
|
|
58
90
|
});
|
|
59
|
-
const
|
|
91
|
+
const F = (e) => {
|
|
60
92
|
const t = {
|
|
61
93
|
kind: "node",
|
|
62
94
|
id: e.id
|
|
63
|
-
},
|
|
95
|
+
}, n = {
|
|
64
96
|
selected: () => A(t),
|
|
65
|
-
openMenu: (
|
|
97
|
+
openMenu: (r) => z(t, r)
|
|
66
98
|
};
|
|
67
99
|
return (() => {
|
|
68
|
-
var
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
var
|
|
73
|
-
return () =>
|
|
74
|
-
})()), S((
|
|
75
|
-
var
|
|
76
|
-
return
|
|
100
|
+
var r = ve();
|
|
101
|
+
return r.$$keydown = (a) => G(t, a), r.$$contextmenu = (a) => z(t, a), r.$$click = (a) => {
|
|
102
|
+
a.target.closest("button, a, input, select, textarea, [data-floe-canvas-interactive]") || (a.stopPropagation(), i.onActivate?.(k(t, a.currentTarget, a)));
|
|
103
|
+
}, r.$$focusout = () => f(null), r.$$focusin = () => f(t), r.addEventListener("pointerleave", () => f(null)), r.addEventListener("pointerenter", () => f(t)), w(r, (() => {
|
|
104
|
+
var a = ae(() => !!(e.kind === "group" && i.renderGroup));
|
|
105
|
+
return () => a() ? i.renderGroup(e, n) : i.renderNode(e, n);
|
|
106
|
+
})()), S((a) => {
|
|
107
|
+
var m = e.kind === "group" ? "floe-graph__group" : "floe-graph__node", c = e.id, d = A(t), _ = `${e.x}px`, P = `${e.y}px`, $ = `${e.width}px`, u = `${e.height}px`, v = e.label;
|
|
108
|
+
return m !== a.e && K(r, a.e = m), c !== a.t && l(r, "data-graph-object", a.t = c), d !== a.a && l(r, "data-selected", a.a = d), _ !== a.o && T(r, "left", a.o = _), P !== a.i && T(r, "top", a.i = P), $ !== a.n && T(r, "width", a.n = $), u !== a.s && T(r, "height", a.s = u), v !== a.h && l(r, "aria-label", a.h = v), a;
|
|
77
109
|
}, {
|
|
78
110
|
e: void 0,
|
|
79
111
|
t: void 0,
|
|
@@ -83,14 +115,14 @@ function ke(i) {
|
|
|
83
115
|
n: void 0,
|
|
84
116
|
s: void 0,
|
|
85
117
|
h: void 0
|
|
86
|
-
}),
|
|
118
|
+
}), r;
|
|
87
119
|
})();
|
|
88
120
|
};
|
|
89
121
|
return (() => {
|
|
90
|
-
var e =
|
|
91
|
-
e.$$keydown = (
|
|
122
|
+
var e = me();
|
|
123
|
+
e.$$keydown = (n) => G(null, n);
|
|
92
124
|
var t = g;
|
|
93
|
-
return typeof t == "function" ?
|
|
125
|
+
return typeof t == "function" ? ie(t, e) : g = e, w(e, x(ue, {
|
|
94
126
|
get viewport() {
|
|
95
127
|
return i.viewport;
|
|
96
128
|
},
|
|
@@ -103,62 +135,64 @@ function ke(i) {
|
|
|
103
135
|
return i.onViewportChange;
|
|
104
136
|
},
|
|
105
137
|
onViewportInteractionStart: () => i.onInteractionStart?.(),
|
|
106
|
-
resolveTargetRole: (
|
|
107
|
-
onCanvasPointerDown: (
|
|
108
|
-
!(
|
|
138
|
+
resolveTargetRole: (n) => (n.target instanceof Element ? n.target : null)?.closest('button, a, input, select, textarea, [data-floe-canvas-interactive="true"]') ? "local_surface" : se(n),
|
|
139
|
+
onCanvasPointerDown: (n) => {
|
|
140
|
+
!(n.target instanceof Element) || n.target.closest("[data-graph-object]") || i.onActivate?.(k(null, g, n));
|
|
109
141
|
},
|
|
110
|
-
onCanvasContextMenu: (
|
|
142
|
+
onCanvasContextMenu: (n) => i.onContextMenu?.({
|
|
111
143
|
object: null,
|
|
112
144
|
owner: g,
|
|
113
145
|
position: {
|
|
114
|
-
x:
|
|
115
|
-
y:
|
|
146
|
+
x: n.clientX,
|
|
147
|
+
y: n.clientY
|
|
116
148
|
}
|
|
117
149
|
}),
|
|
118
|
-
children: (
|
|
119
|
-
const
|
|
120
|
-
return [
|
|
150
|
+
children: (n) => {
|
|
151
|
+
const r = y(() => te(n())), a = y(() => r().filter((d) => d.kind === "group")), m = y(() => r().filter((d) => d.kind !== "group")), c = y(() => ne(n()));
|
|
152
|
+
return [x(j, {
|
|
121
153
|
get each() {
|
|
122
|
-
return
|
|
154
|
+
return a();
|
|
123
155
|
},
|
|
124
|
-
children:
|
|
156
|
+
children: F
|
|
125
157
|
}), (() => {
|
|
126
|
-
var
|
|
127
|
-
return l(P, "id", H),
|
|
158
|
+
var d = be(), _ = d.firstChild, P = _.firstChild;
|
|
159
|
+
return l(P, "id", H), w(d, x(j, {
|
|
128
160
|
get each() {
|
|
129
|
-
return
|
|
161
|
+
return c();
|
|
130
162
|
},
|
|
131
|
-
children: (
|
|
132
|
-
const
|
|
163
|
+
children: ($) => {
|
|
164
|
+
const {
|
|
165
|
+
edge: u
|
|
166
|
+
} = $, v = {
|
|
133
167
|
kind: "edge",
|
|
134
|
-
id:
|
|
135
|
-
},
|
|
136
|
-
return
|
|
168
|
+
id: u.id
|
|
169
|
+
}, W = () => $.path, re = () => $.label;
|
|
170
|
+
return x(D, {
|
|
137
171
|
get when() {
|
|
138
|
-
return !Y() || Y().has(
|
|
172
|
+
return !Y() || Y().has(u.id);
|
|
139
173
|
},
|
|
140
174
|
get children() {
|
|
141
|
-
var
|
|
142
|
-
return l(
|
|
175
|
+
var C = xe(), R = C.firstChild, s = R.nextSibling;
|
|
176
|
+
return l(R, "marker-end", `url(#${H})`), w(C, x(D, {
|
|
143
177
|
get when() {
|
|
144
|
-
return
|
|
178
|
+
return re();
|
|
145
179
|
},
|
|
146
180
|
children: (o) => (() => {
|
|
147
|
-
var
|
|
148
|
-
return
|
|
149
|
-
var
|
|
150
|
-
return
|
|
181
|
+
var b = ye();
|
|
182
|
+
return w(b, () => u.label), S((h) => {
|
|
183
|
+
var M = /^\d+$/.test(u.label), E = o().x, L = o().y - 6;
|
|
184
|
+
return M !== h.e && l(b, "data-count", h.e = M), E !== h.t && l(b, "x", h.t = E), L !== h.a && l(b, "y", h.a = L), h;
|
|
151
185
|
}, {
|
|
152
186
|
e: void 0,
|
|
153
187
|
t: void 0,
|
|
154
188
|
a: void 0
|
|
155
|
-
}),
|
|
189
|
+
}), b;
|
|
156
190
|
})()
|
|
157
|
-
}),
|
|
158
|
-
o.stopPropagation(), i.onActivate?.(
|
|
159
|
-
},
|
|
160
|
-
var
|
|
161
|
-
return
|
|
191
|
+
}), s), s.$$keydown = (o) => G(v, o), s.$$contextmenu = (o) => z(v, o), s.$$click = (o) => {
|
|
192
|
+
o.stopPropagation(), i.onActivate?.(k(v, o.currentTarget, o));
|
|
193
|
+
}, s.addEventListener("blur", () => f(null)), s.addEventListener("focus", () => f(v)), s.addEventListener("pointerleave", () => f(null)), s.addEventListener("pointerenter", () => f(v)), S((o) => {
|
|
194
|
+
var b = u.id, h = ee().has(u.id), M = A(v), E = W(), L = W(), q = u.label;
|
|
195
|
+
return b !== o.e && l(C, "data-graph-object", o.e = b), h !== o.t && l(C, "data-emphasized", o.t = h), M !== o.a && l(C, "data-selected", o.a = M), E !== o.o && l(R, "d", o.o = E), L !== o.i && l(s, "d", o.i = L), q !== o.n && l(s, "aria-label", o.n = q), o;
|
|
162
196
|
}, {
|
|
163
197
|
e: void 0,
|
|
164
198
|
t: void 0,
|
|
@@ -166,28 +200,52 @@ function ke(i) {
|
|
|
166
200
|
o: void 0,
|
|
167
201
|
i: void 0,
|
|
168
202
|
n: void 0
|
|
169
|
-
}),
|
|
203
|
+
}), C;
|
|
170
204
|
}
|
|
171
205
|
});
|
|
172
206
|
}
|
|
173
|
-
}), null), S(() => l(
|
|
174
|
-
})(),
|
|
207
|
+
}), null), S(() => l(d, "aria-label", i.ariaLabel)), d;
|
|
208
|
+
})(), x(j, {
|
|
175
209
|
get each() {
|
|
176
|
-
return
|
|
210
|
+
return m();
|
|
177
211
|
},
|
|
178
|
-
children:
|
|
212
|
+
children: F
|
|
179
213
|
})];
|
|
180
214
|
}
|
|
181
|
-
}), null),
|
|
182
|
-
|
|
183
|
-
|
|
215
|
+
}), null), w(e, x(D, {
|
|
216
|
+
get when() {
|
|
217
|
+
return i.minimap;
|
|
218
|
+
},
|
|
219
|
+
children: (n) => x(fe, {
|
|
220
|
+
get layout() {
|
|
221
|
+
return i.layout;
|
|
222
|
+
},
|
|
223
|
+
get viewport() {
|
|
224
|
+
return i.viewport;
|
|
225
|
+
},
|
|
226
|
+
get size() {
|
|
227
|
+
return V();
|
|
228
|
+
},
|
|
229
|
+
get onViewportChange() {
|
|
230
|
+
return i.onViewportChange;
|
|
231
|
+
},
|
|
232
|
+
get onInteractionStart() {
|
|
233
|
+
return i.onInteractionStart;
|
|
234
|
+
},
|
|
235
|
+
get ariaLabel() {
|
|
236
|
+
return n().ariaLabel;
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
}), null), w(e, () => i.overlay, null), S((n) => {
|
|
240
|
+
var r = `floe-graph ${i.class ?? ""}`, a = i.ariaLabel;
|
|
241
|
+
return r !== n.e && K(e, n.e = r), a !== n.t && l(e, "aria-label", n.t = a), n;
|
|
184
242
|
}, {
|
|
185
243
|
e: void 0,
|
|
186
244
|
t: void 0
|
|
187
245
|
}), e;
|
|
188
246
|
})();
|
|
189
247
|
}
|
|
190
|
-
|
|
248
|
+
oe(["focusin", "focusout", "click", "contextmenu", "keydown"]);
|
|
191
249
|
export {
|
|
192
|
-
|
|
250
|
+
Le as GraphCanvas
|
|
193
251
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { GraphLayout, GraphViewport } from './types';
|
|
2
|
+
export interface GraphMinimapProps {
|
|
3
|
+
layout: GraphLayout;
|
|
4
|
+
viewport: GraphViewport;
|
|
5
|
+
size: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
onViewportChange: (viewport: GraphViewport) => void;
|
|
10
|
+
onInteractionStart?: () => void;
|
|
11
|
+
ariaLabel: string;
|
|
12
|
+
}
|
|
13
|
+
/** A lightweight navigator over the exact main-canvas geometry. No second layout. */
|
|
14
|
+
export declare function GraphMinimap(props: GraphMinimapProps): import("solid-js").JSX.Element;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { effect as S, setAttribute as d, template as z, use as A, delegateEvents as k } from "solid-js/web";
|
|
2
|
+
import { createMemo as w } from "solid-js";
|
|
3
|
+
import { graphSectionPath as D, fitGraphViewport as L } from "./geometry.js";
|
|
4
|
+
var V = /* @__PURE__ */ z('<svg class=floe-graph__minimap role=region tabindex=0 preserveAspectRatio="xMidYMid meet"data-floe-canvas-interactive=true><path class=floe-graph__minimap-groups></path><path class=floe-graph__minimap-edges></path><path class=floe-graph__minimap-nodes></path><rect class=floe-graph__minimap-viewport>');
|
|
5
|
+
function R(e) {
|
|
6
|
+
let h, n;
|
|
7
|
+
const c = w(() => {
|
|
8
|
+
const {
|
|
9
|
+
x: i,
|
|
10
|
+
y: o,
|
|
11
|
+
width: s,
|
|
12
|
+
height: v
|
|
13
|
+
} = e.layout.bounds, a = Math.max(s, v, 1) * 0.04;
|
|
14
|
+
return {
|
|
15
|
+
x: i - a,
|
|
16
|
+
y: o - a,
|
|
17
|
+
width: s + a * 2,
|
|
18
|
+
height: v + a * 2
|
|
19
|
+
};
|
|
20
|
+
}), g = (i) => e.layout.nodes.filter((o) => (o.kind === "group" ? "group" : "node") === i).map((o) => `M${o.x},${o.y}h${o.width}v${o.height}h${-o.width}Z`).join(""), C = w(() => g("node")), I = w(() => g("group")), P = w(() => e.layout.edges.flatMap((i) => i.sections.map(D)).join(" ")), u = (i) => {
|
|
21
|
+
const o = h?.getScreenCTM();
|
|
22
|
+
return o ? new DOMPoint(i.clientX, i.clientY).matrixTransform(o.inverse()) : void 0;
|
|
23
|
+
}, f = (i) => {
|
|
24
|
+
n?.id === i.pointerId && (n = void 0, h?.hasPointerCapture(i.pointerId) && h.releasePointerCapture(i.pointerId));
|
|
25
|
+
};
|
|
26
|
+
return (() => {
|
|
27
|
+
var i = V(), o = i.firstChild, s = o.nextSibling, v = s.nextSibling, a = v.nextSibling;
|
|
28
|
+
i.$$keydown = (t) => {
|
|
29
|
+
const l = {
|
|
30
|
+
ArrowLeft: [1, 0],
|
|
31
|
+
ArrowRight: [-1, 0],
|
|
32
|
+
ArrowUp: [0, 1],
|
|
33
|
+
ArrowDown: [0, -1]
|
|
34
|
+
}[t.key];
|
|
35
|
+
!l && t.key !== "Home" || (t.preventDefault(), t.stopPropagation(), e.onInteractionStart?.(), e.onViewportChange(l ? {
|
|
36
|
+
...e.viewport,
|
|
37
|
+
x: e.viewport.x + l[0] * e.size.width * 0.2,
|
|
38
|
+
y: e.viewport.y + l[1] * e.size.height * 0.2
|
|
39
|
+
} : L(e.layout.bounds, e.size, 24)));
|
|
40
|
+
}, i.addEventListener("lostpointercapture", () => {
|
|
41
|
+
n = void 0;
|
|
42
|
+
}), i.addEventListener("pointercancel", f), i.$$pointerup = f, i.$$pointermove = (t) => {
|
|
43
|
+
if (n?.id !== t.pointerId) return;
|
|
44
|
+
const r = u(t);
|
|
45
|
+
r && e.onViewportChange({
|
|
46
|
+
...n.viewport,
|
|
47
|
+
x: n.viewport.x - (r.x - n.x) * n.viewport.scale,
|
|
48
|
+
y: n.viewport.y - (r.y - n.y) * n.viewport.scale
|
|
49
|
+
});
|
|
50
|
+
}, i.$$pointerdown = (t) => {
|
|
51
|
+
if (t.button !== 0) return;
|
|
52
|
+
const r = u(t);
|
|
53
|
+
r && (t.preventDefault(), t.stopPropagation(), e.onInteractionStart?.(), h.focus({
|
|
54
|
+
preventScroll: !0
|
|
55
|
+
}), t.target.matches(".floe-graph__minimap-viewport") || e.onViewportChange({
|
|
56
|
+
...e.viewport,
|
|
57
|
+
x: e.size.width / 2 - r.x * e.viewport.scale,
|
|
58
|
+
y: e.size.height / 2 - r.y * e.viewport.scale
|
|
59
|
+
}), n = {
|
|
60
|
+
id: t.pointerId,
|
|
61
|
+
x: r.x,
|
|
62
|
+
y: r.y,
|
|
63
|
+
viewport: {
|
|
64
|
+
...e.viewport
|
|
65
|
+
}
|
|
66
|
+
}, h.setPointerCapture(t.pointerId));
|
|
67
|
+
};
|
|
68
|
+
var m = h;
|
|
69
|
+
return typeof m == "function" ? A(m, i) : h = i, S((t) => {
|
|
70
|
+
var r = e.ariaLabel, l = `${c().x} ${c().y} ${c().width} ${c().height}`, x = I(), y = P(), p = C(), $ = -e.viewport.x / e.viewport.scale, b = -e.viewport.y / e.viewport.scale, _ = e.size.width / e.viewport.scale, M = e.size.height / e.viewport.scale;
|
|
71
|
+
return r !== t.e && d(i, "aria-label", t.e = r), l !== t.t && d(i, "viewBox", t.t = l), x !== t.a && d(o, "d", t.a = x), y !== t.o && d(s, "d", t.o = y), p !== t.i && d(v, "d", t.i = p), $ !== t.n && d(a, "x", t.n = $), b !== t.s && d(a, "y", t.s = b), _ !== t.h && d(a, "width", t.h = _), M !== t.r && d(a, "height", t.r = M), t;
|
|
72
|
+
}, {
|
|
73
|
+
e: void 0,
|
|
74
|
+
t: void 0,
|
|
75
|
+
a: void 0,
|
|
76
|
+
o: void 0,
|
|
77
|
+
i: void 0,
|
|
78
|
+
n: void 0,
|
|
79
|
+
s: void 0,
|
|
80
|
+
h: void 0,
|
|
81
|
+
r: void 0
|
|
82
|
+
}), i;
|
|
83
|
+
})();
|
|
84
|
+
}
|
|
85
|
+
k(["pointerdown", "pointermove", "pointerup", "keydown"]);
|
|
86
|
+
export {
|
|
87
|
+
R as GraphMinimap
|
|
88
|
+
};
|
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
function c() {
|
|
4
|
-
const r = new Worker(new URL(
|
|
1
|
+
function w() {
|
|
2
|
+
const t = new Worker(new URL(
|
|
5
3
|
/* @vite-ignore */
|
|
6
|
-
"" + new URL("../../assets/
|
|
4
|
+
"" + new URL("../../assets/layout-worker-BK6m515B.js", import.meta.url).href,
|
|
7
5
|
import.meta.url
|
|
8
|
-
), { type: "module" })
|
|
9
|
-
let
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
for (const
|
|
13
|
-
|
|
6
|
+
), { type: "module" });
|
|
7
|
+
let s, u = 0;
|
|
8
|
+
const o = /* @__PURE__ */ new Map(), n = (e) => {
|
|
9
|
+
s = e, t.terminate();
|
|
10
|
+
for (const r of o.values()) r.reject(e);
|
|
11
|
+
o.clear();
|
|
14
12
|
};
|
|
15
|
-
return
|
|
13
|
+
return t.addEventListener(
|
|
16
14
|
"error",
|
|
17
15
|
(e) => n(new Error(e.message || "Graph layout worker failed"))
|
|
18
|
-
),
|
|
16
|
+
), t.addEventListener(
|
|
19
17
|
"messageerror",
|
|
20
18
|
() => n(new Error("Invalid graph layout worker response"))
|
|
21
|
-
), {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
), t.addEventListener("message", ({ data: e }) => {
|
|
20
|
+
if (!e || !Number.isInteger(e.id) || !e.error && !e.layout) {
|
|
21
|
+
n(new Error("Invalid graph layout worker response"));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const r = o.get(e.id);
|
|
25
|
+
r && (o.delete(e.id), e.error ? r.reject(new Error(e.error)) : r.resolve(e.layout));
|
|
26
|
+
}), {
|
|
27
|
+
layout(e, r) {
|
|
28
|
+
return s ? Promise.reject(s) : new Promise((a, l) => {
|
|
29
|
+
const i = ++u;
|
|
30
|
+
o.set(i, { resolve: a, reject: l });
|
|
31
|
+
try {
|
|
32
|
+
t.postMessage({ id: i, input: e, options: r ?? {} });
|
|
33
|
+
} catch (p) {
|
|
34
|
+
o.delete(i), l(p);
|
|
35
|
+
}
|
|
26
36
|
});
|
|
27
37
|
},
|
|
28
38
|
dispose() {
|
|
@@ -31,5 +41,5 @@ function c() {
|
|
|
31
41
|
};
|
|
32
42
|
}
|
|
33
43
|
export {
|
|
34
|
-
|
|
44
|
+
w as createGraphLayoutEngine
|
|
35
45
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/graph.css
CHANGED
|
@@ -69,6 +69,57 @@
|
|
|
69
69
|
stroke: var(--graph-edge-active, var(--foreground));
|
|
70
70
|
stroke-width: 3px;
|
|
71
71
|
}
|
|
72
|
+
.floe-graph__minimap {
|
|
73
|
+
position: absolute;
|
|
74
|
+
right: 16px;
|
|
75
|
+
bottom: 16px;
|
|
76
|
+
z-index: 4;
|
|
77
|
+
width: clamp(112px, 20vw, 196px);
|
|
78
|
+
height: clamp(72px, 12vw, 120px);
|
|
79
|
+
border: 1px solid var(--border);
|
|
80
|
+
border-radius: 9px;
|
|
81
|
+
background: color-mix(in srgb, var(--card) 94%, transparent);
|
|
82
|
+
box-shadow: 0 3px 14px rgb(0 0 0 / 8%);
|
|
83
|
+
cursor: crosshair;
|
|
84
|
+
touch-action: none;
|
|
85
|
+
user-select: none;
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
}
|
|
88
|
+
.floe-graph__minimap:focus-visible {
|
|
89
|
+
outline: 2px solid var(--ring);
|
|
90
|
+
outline-offset: 2px;
|
|
91
|
+
}
|
|
92
|
+
.floe-graph__minimap-nodes {
|
|
93
|
+
fill: var(--muted-foreground);
|
|
94
|
+
opacity: 0.65;
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
}
|
|
97
|
+
.floe-graph__minimap-groups {
|
|
98
|
+
fill: color-mix(in srgb, var(--primary) 10%, transparent);
|
|
99
|
+
stroke: var(--muted-foreground);
|
|
100
|
+
stroke-width: 0.7px;
|
|
101
|
+
vector-effect: non-scaling-stroke;
|
|
102
|
+
pointer-events: none;
|
|
103
|
+
}
|
|
104
|
+
.floe-graph__minimap-edges {
|
|
105
|
+
fill: none;
|
|
106
|
+
stroke: var(--muted-foreground);
|
|
107
|
+
stroke-width: 0.5px;
|
|
108
|
+
vector-effect: non-scaling-stroke;
|
|
109
|
+
opacity: 0.35;
|
|
110
|
+
pointer-events: none;
|
|
111
|
+
}
|
|
112
|
+
.floe-graph__minimap-viewport {
|
|
113
|
+
fill: color-mix(in srgb, var(--primary) 12%, transparent);
|
|
114
|
+
stroke: var(--primary);
|
|
115
|
+
stroke-width: 1.5px;
|
|
116
|
+
vector-effect: non-scaling-stroke;
|
|
117
|
+
cursor: grab;
|
|
118
|
+
}
|
|
119
|
+
.floe-graph__minimap:active,
|
|
120
|
+
.floe-graph__minimap:active .floe-graph__minimap-viewport {
|
|
121
|
+
cursor: grabbing;
|
|
122
|
+
}
|
|
72
123
|
.floe-graph__node:focus-visible,
|
|
73
124
|
.floe-graph__group:focus-visible {
|
|
74
125
|
outline: 2px solid var(--ring);
|
|
@@ -90,6 +141,21 @@
|
|
|
90
141
|
.floe-graph__group:focus-visible {
|
|
91
142
|
outline-color: Highlight;
|
|
92
143
|
}
|
|
144
|
+
.floe-graph__minimap {
|
|
145
|
+
background: Canvas;
|
|
146
|
+
border-color: CanvasText;
|
|
147
|
+
}
|
|
148
|
+
.floe-graph__minimap-nodes {
|
|
149
|
+
fill: CanvasText;
|
|
150
|
+
}
|
|
151
|
+
.floe-graph__minimap-groups,
|
|
152
|
+
.floe-graph__minimap-edges {
|
|
153
|
+
stroke: CanvasText;
|
|
154
|
+
}
|
|
155
|
+
.floe-graph__minimap-viewport {
|
|
156
|
+
stroke: Highlight;
|
|
157
|
+
fill: transparent;
|
|
158
|
+
}
|
|
93
159
|
}
|
|
94
160
|
|
|
95
161
|
.floe-graph__edge-label {
|
package/dist/graph.d.ts
CHANGED
package/dist/graph.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { fitGraphViewport as e, graphEdgeLabelPosition as o, graphRelatedEdges as
|
|
2
|
-
import { createGraphLayoutEngine as
|
|
1
|
+
import { fitGraphViewport as e, graphEdgeLabelPosition as o, graphRelatedEdges as p, graphSectionPath as t } from "./components/graph/geometry.js";
|
|
2
|
+
import { createGraphLayoutEngine as i } from "./components/graph/engine.js";
|
|
3
3
|
import { GraphCanvas as n } from "./components/graph/GraphCanvas.js";
|
|
4
|
+
import { GraphMinimap as m } from "./components/graph/GraphMinimap.js";
|
|
4
5
|
export {
|
|
5
6
|
n as GraphCanvas,
|
|
6
|
-
|
|
7
|
+
m as GraphMinimap,
|
|
8
|
+
i as createGraphLayoutEngine,
|
|
7
9
|
e as fitGraphViewport,
|
|
8
10
|
o as graphEdgeLabelPosition,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
p as graphRelatedEdges,
|
|
12
|
+
t as graphSectionPath
|
|
11
13
|
};
|