@floegence/floe-webapp-core 0.83.1 → 0.85.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.
Files changed (19) hide show
  1. package/dist/components/file-browser/DragPreview.js +1 -1
  2. package/dist/components/graph/GraphCanvas.js +93 -78
  3. package/dist/components/graph/geometry.d.ts +2 -0
  4. package/dist/components/graph/geometry.js +29 -19
  5. package/dist/components/graph/layout.js +71 -66
  6. package/dist/components/graph/positions.d.ts +3 -0
  7. package/dist/components/graph/positions.js +169 -0
  8. package/dist/components/graph/types.d.ts +6 -0
  9. package/dist/components/notes/NotesOverlay.js +1 -1
  10. package/dist/components/workbench/WorkbenchFilterBar.js +1 -1
  11. package/dist/components/workbench/WorkbenchLockButton.js +1 -1
  12. package/dist/components/workbench/WorkbenchOverlay.js +1 -1
  13. package/dist/graph.css +18 -0
  14. package/dist/graph.js +7 -6
  15. package/dist/node_modules/.pnpm/{solid-motionone@1.0.4_solid-js@1.9.15 → solid-motionone@1.0.4_solid-js@1.9.17}/node_modules/solid-motionone/dist/index.js +3 -3
  16. package/package.json +3 -3
  17. /package/dist/node_modules/.pnpm/{@solid-primitives_props@3.2.4_solid-js@1.9.15 → @solid-primitives_props@3.2.4_solid-js@1.9.17}/node_modules/@solid-primitives/props/dist/combineProps.js +0 -0
  18. /package/dist/node_modules/.pnpm/{@solid-primitives_refs@1.1.4_solid-js@1.9.15 → @solid-primitives_refs@1.1.4_solid-js@1.9.17}/node_modules/@solid-primitives/refs/dist/index.js +0 -0
  19. /package/dist/node_modules/.pnpm/{@solid-primitives_transition-group@1.1.2_solid-js@1.9.15 → @solid-primitives_transition-group@1.1.2_solid-js@1.9.17}/node_modules/@solid-primitives/transition-group/dist/index.js +0 -0
@@ -1,6 +1,6 @@
1
1
  import { createComponent as o, Portal as N, insert as l, effect as u, className as $, memo as B, template as a, setAttribute as A } from "solid-js/web";
2
2
  import { createSignal as F, createEffect as V, createMemo as d, Show as m, For as j } from "solid-js";
3
- import { Presence as U, Motion as X } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.15/node_modules/solid-motionone/dist/index.js";
3
+ import { Presence as U, Motion as X } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.17/node_modules/solid-motionone/dist/index.js";
4
4
  import { cn as f } from "../../utils/cn.js";
5
5
  import { useFileBrowserDrag as G } from "../../context/FileBrowserDragContext.js";
6
6
  import { FileItemIcon as W } from "./FileIcons.js";
@@ -1,34 +1,34 @@
1
- import { insert as w, createComponent as y, setAttribute as c, effect as C, className as N, template as M, memo as Q, setStyleProperty as E, use as Z, delegateEvents as p } from "solid-js/web";
2
- import { createUniqueId as ee, createSignal as V, createMemo as k, onMount as te, For as P, Show as ne, onCleanup as re } from "solid-js";
3
- import { InfiniteCanvas as ae } from "../ui/InfiniteCanvas.js";
4
- import { resolveSurfaceInteractionTargetRole as ie } from "../ui/localInteractionSurface.js";
5
- import { graphRelatedEdges as B, graphSectionPath as oe } from "./geometry.js";
6
- var le = /* @__PURE__ */ M("<div data-floe-canvas-pan-surface=true role=group tabindex=0>"), ce = /* @__PURE__ */ M("<div role=region tabindex=0>"), de = /* @__PURE__ */ M('<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>'), ue = /* @__PURE__ */ M("<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);
7
- function me(i) {
8
- const T = `graph-arrow-${ee()}`;
9
- let u;
10
- const [F, W] = V(null), [q, K] = V({
1
+ import { insert as y, createComponent as w, setAttribute as l, effect as S, className as V, template as _, memo as p, setStyleProperty as T, use as ee, delegateEvents as te } from "solid-js/web";
2
+ import { createUniqueId as ne, createSignal as B, createMemo as $, onMount as re, For as D, Show as F, onCleanup as ae } from "solid-js";
3
+ import { InfiniteCanvas as ie } from "../ui/InfiniteCanvas.js";
4
+ import { resolveSurfaceInteractionTargetRole as oe } from "../ui/localInteractionSurface.js";
5
+ import { graphRelatedEdges as W, graphEdgeLabelPosition as le, graphSectionPath as ce } from "./geometry.js";
6
+ var de = /* @__PURE__ */ _("<div data-floe-canvas-pan-surface=true role=group tabindex=0>"), se = /* @__PURE__ */ _("<div role=region tabindex=0>"), ue = /* @__PURE__ */ _('<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>'), he = /* @__PURE__ */ _("<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), ge = /* @__PURE__ */ _("<svg><text class=floe-graph__edge-label aria-hidden=true></svg>", !1, !0, !1);
7
+ function ke(i) {
8
+ const H = `graph-arrow-${ne()}`;
9
+ let g;
10
+ const [q, K] = B(null), [O, U] = B({
11
11
  width: 0,
12
12
  height: 0
13
- }), A = () => i.highlight === void 0 ? F() : i.highlight, O = k(() => new Map(i.layout.nodes.map((e) => [e.id, e]))), U = k(() => {
14
- const e = A();
15
- return e?.kind === "node" ? B(i.layout, e.id) : new Set(e ? [e.id] : []);
16
- }), R = k(() => {
17
- const e = A();
13
+ }), X = () => i.highlight === void 0 ? q() : i.highlight, J = $(() => new Map(i.layout.nodes.map((e) => [e.id, e]))), Q = $(() => {
14
+ const e = X();
15
+ return e?.kind === "node" ? W(i.layout, e.id) : new Set(e ? [e.id] : []);
16
+ }), Y = $(() => {
17
+ const e = X();
18
18
  if (e?.kind !== "node") return null;
19
- const t = O().get(e.id), r = t?.kind === "group" ? t.id : t?.parentId;
20
- return r ? B(i.layout, r) : null;
21
- }), S = (e) => i.selected?.kind === e.kind && i.selected.id === e.id, J = (e) => {
19
+ const t = J().get(e.id), r = t?.kind === "group" ? t.id : t?.parentId;
20
+ return r ? W(i.layout, r) : null;
21
+ }), A = (e) => i.selected?.kind === e.kind && i.selected.id === e.id, Z = (e) => {
22
22
  const {
23
23
  width: t,
24
24
  height: r
25
- } = q();
25
+ } = O();
26
26
  if (!t || !r) return i.layout.nodes;
27
- const a = -e.x / e.scale - 240, n = -e.y / e.scale - 240, x = a + t / e.scale + 480, l = n + r / e.scale + 480;
28
- return i.layout.nodes.filter((d) => d.id === i.selected?.id || d.x + d.width >= a && d.x <= x && d.y + d.height >= n && d.y <= l);
29
- }, s = (e) => {
30
- W(e), i.onHover?.(e);
31
- }, m = (e, t, r) => {
27
+ const a = -e.x / e.scale - 240, n = -e.y / e.scale - 240, b = a + t / e.scale + 480, c = n + r / e.scale + 480;
28
+ return i.layout.nodes.filter((d) => d.id === i.selected?.id || d.x + d.width >= a && d.x <= b && d.y + d.height >= n && d.y <= c);
29
+ }, v = (e) => {
30
+ K(e), i.onHover?.(e);
31
+ }, x = (e, t, r) => {
32
32
  const a = t.getBoundingClientRect();
33
33
  return {
34
34
  object: e,
@@ -41,39 +41,39 @@ function me(i) {
41
41
  y: a.top + Math.min(32, a.height / 2)
42
42
  }
43
43
  };
44
- }, L = (e, t) => {
45
- i.onContextMenu && (t.preventDefault(), t.stopPropagation(), i.onContextMenu(m(e, t.currentTarget, t)));
46
- }, _ = (e, t) => {
47
- t.target === t.currentTarget && (t.key === "ContextMenu" || t.shiftKey && t.key === "F10" ? (t.preventDefault(), t.stopPropagation(), i.onContextMenu?.(m(e, t.currentTarget))) : t.key === "Enter" ? (t.preventDefault(), t.stopPropagation(), i.onActivate?.(m(e, t.currentTarget))) : t.key === "Escape" && (s(null), i.onActivate?.(m(null, u))));
44
+ }, R = (e, t) => {
45
+ i.onContextMenu && (t.preventDefault(), t.stopPropagation(), i.onContextMenu(x(e, t.currentTarget, t)));
46
+ }, j = (e, t) => {
47
+ t.target === t.currentTarget && (t.key === "ContextMenu" || t.shiftKey && t.key === "F10" ? (t.preventDefault(), t.stopPropagation(), i.onContextMenu?.(x(e, t.currentTarget))) : t.key === "Enter" ? (t.preventDefault(), t.stopPropagation(), i.onActivate?.(x(e, t.currentTarget))) : t.key === "Escape" && (v(null), i.onActivate?.(x(null, g))));
48
48
  };
49
- te(() => {
50
- if (!u) return;
51
- const e = () => K({
52
- width: u.clientWidth,
53
- height: u.clientHeight
49
+ re(() => {
50
+ if (!g) return;
51
+ const e = () => U({
52
+ width: g.clientWidth,
53
+ height: g.clientHeight
54
54
  });
55
55
  e();
56
56
  const t = new ResizeObserver(e);
57
- t.observe(u), re(() => t.disconnect());
57
+ t.observe(g), ae(() => t.disconnect());
58
58
  });
59
- const j = (e) => {
59
+ const G = (e) => {
60
60
  const t = {
61
61
  kind: "node",
62
62
  id: e.id
63
63
  }, r = {
64
- selected: () => S(t),
65
- openMenu: (a) => L(t, a)
64
+ selected: () => A(t),
65
+ openMenu: (a) => R(t, a)
66
66
  };
67
67
  return (() => {
68
- var a = le();
69
- return a.$$keydown = (n) => _(t, n), a.$$contextmenu = (n) => L(t, n), a.$$click = (n) => {
70
- n.target.closest("button, a, input, select, textarea, [data-floe-canvas-interactive]") || (n.stopPropagation(), i.onActivate?.(m(t, n.currentTarget, n)));
71
- }, a.$$focusout = () => s(null), a.$$focusin = () => s(t), a.addEventListener("pointerleave", () => s(null)), a.addEventListener("pointerenter", () => s(t)), w(a, (() => {
72
- var n = Q(() => !!(e.kind === "group" && i.renderGroup));
68
+ var a = de();
69
+ return a.$$keydown = (n) => j(t, n), a.$$contextmenu = (n) => R(t, n), a.$$click = (n) => {
70
+ n.target.closest("button, a, input, select, textarea, [data-floe-canvas-interactive]") || (n.stopPropagation(), i.onActivate?.(x(t, n.currentTarget, n)));
71
+ }, a.$$focusout = () => v(null), a.$$focusin = () => v(t), a.addEventListener("pointerleave", () => v(null)), a.addEventListener("pointerenter", () => v(t)), y(a, (() => {
72
+ var n = p(() => !!(e.kind === "group" && i.renderGroup));
73
73
  return () => n() ? i.renderGroup(e, r) : i.renderNode(e, r);
74
- })()), C((n) => {
75
- var x = e.kind === "group" ? "floe-graph__group" : "floe-graph__node", l = e.id, d = S(t), $ = `${e.x}px`, h = `${e.y}px`, g = `${e.width}px`, b = `${e.height}px`, v = e.label;
76
- return x !== n.e && N(a, n.e = x), l !== n.t && c(a, "data-graph-object", n.t = l), d !== n.a && c(a, "data-selected", n.a = d), $ !== n.o && E(a, "left", n.o = $), h !== n.i && E(a, "top", n.i = h), g !== n.n && E(a, "width", n.n = g), b !== n.s && E(a, "height", n.s = b), v !== n.h && c(a, "aria-label", n.h = v), n;
74
+ })()), S((n) => {
75
+ var b = e.kind === "group" ? "floe-graph__group" : "floe-graph__node", c = e.id, d = A(t), P = `${e.x}px`, s = `${e.y}px`, f = `${e.width}px`, C = `${e.height}px`, I = e.label;
76
+ return b !== n.e && V(a, n.e = b), c !== n.t && l(a, "data-graph-object", n.t = c), d !== n.a && l(a, "data-selected", n.a = d), P !== n.o && T(a, "left", n.o = P), s !== n.i && T(a, "top", n.i = s), f !== n.n && T(a, "width", n.n = f), C !== n.s && T(a, "height", n.s = C), I !== n.h && l(a, "aria-label", n.h = I), n;
77
77
  }, {
78
78
  e: void 0,
79
79
  t: void 0,
@@ -87,10 +87,10 @@ function me(i) {
87
87
  })();
88
88
  };
89
89
  return (() => {
90
- var e = ce();
91
- e.$$keydown = (r) => _(null, r);
92
- var t = u;
93
- return typeof t == "function" ? Z(t, e) : u = e, w(e, y(ae, {
90
+ var e = se();
91
+ e.$$keydown = (r) => j(null, r);
92
+ var t = g;
93
+ return typeof t == "function" ? ee(t, e) : g = e, y(e, w(ie, {
94
94
  get viewport() {
95
95
  return i.viewport;
96
96
  },
@@ -103,47 +103,62 @@ function me(i) {
103
103
  return i.onViewportChange;
104
104
  },
105
105
  onViewportInteractionStart: () => i.onInteractionStart?.(),
106
- resolveTargetRole: (r) => (r.target instanceof Element ? r.target : null)?.closest('button, a, input, select, textarea, [data-floe-canvas-interactive="true"]') ? "local_surface" : ie(r),
106
+ resolveTargetRole: (r) => (r.target instanceof Element ? r.target : null)?.closest('button, a, input, select, textarea, [data-floe-canvas-interactive="true"]') ? "local_surface" : oe(r),
107
107
  onCanvasPointerDown: (r) => {
108
- !(r.target instanceof Element) || r.target.closest("[data-graph-object]") || i.onActivate?.(m(null, u, r));
108
+ !(r.target instanceof Element) || r.target.closest("[data-graph-object]") || i.onActivate?.(x(null, g, r));
109
109
  },
110
110
  onCanvasContextMenu: (r) => i.onContextMenu?.({
111
111
  object: null,
112
- owner: u,
112
+ owner: g,
113
113
  position: {
114
114
  x: r.clientX,
115
115
  y: r.clientY
116
116
  }
117
117
  }),
118
118
  children: (r) => {
119
- const a = k(() => J(r())), n = k(() => a().filter((l) => l.kind === "group")), x = k(() => a().filter((l) => l.kind !== "group"));
120
- return [y(P, {
119
+ const a = $(() => Z(r())), n = $(() => a().filter((c) => c.kind === "group")), b = $(() => a().filter((c) => c.kind !== "group"));
120
+ return [w(D, {
121
121
  get each() {
122
122
  return n();
123
123
  },
124
- children: j
124
+ children: G
125
125
  }), (() => {
126
- var l = de(), d = l.firstChild, $ = d.firstChild;
127
- return c($, "id", T), w(l, y(P, {
126
+ var c = ue(), d = c.firstChild, P = d.firstChild;
127
+ return l(P, "id", H), y(c, w(D, {
128
128
  get each() {
129
129
  return i.layout.edges;
130
130
  },
131
- children: (h) => {
132
- const g = {
131
+ children: (s) => {
132
+ const f = {
133
133
  kind: "edge",
134
- id: h.id
135
- }, b = () => h.sections.map(oe).join(" ");
136
- return y(ne, {
134
+ id: s.id
135
+ }, C = () => s.sections.map(ce).join(" "), I = () => le(s.sections);
136
+ return w(F, {
137
137
  get when() {
138
- return !R() || R().has(h.id);
138
+ return !Y() || Y().has(s.id);
139
139
  },
140
140
  get children() {
141
- var v = ue(), I = v.firstChild, f = I.nextSibling;
142
- return c(I, "marker-end", `url(#${T})`), f.$$keydown = (o) => _(g, o), f.$$contextmenu = (o) => L(g, o), f.$$click = (o) => {
143
- o.stopPropagation(), i.onActivate?.(m(g, o.currentTarget, o));
144
- }, f.addEventListener("blur", () => s(null)), f.addEventListener("focus", () => s(g)), f.addEventListener("pointerleave", () => s(null)), f.addEventListener("pointerenter", () => s(g)), C((o) => {
145
- var z = h.id, D = U().has(h.id), H = S(g), X = b(), Y = b(), G = h.label;
146
- return z !== o.e && c(v, "data-graph-object", o.e = z), D !== o.t && c(v, "data-emphasized", o.t = D), H !== o.a && c(v, "data-selected", o.a = H), X !== o.o && c(I, "d", o.o = X), Y !== o.i && c(f, "d", o.i = Y), G !== o.n && c(f, "aria-label", o.n = G), o;
141
+ var k = he(), z = k.firstChild, u = z.nextSibling;
142
+ return l(z, "marker-end", `url(#${H})`), y(k, w(F, {
143
+ get when() {
144
+ return I();
145
+ },
146
+ children: (o) => (() => {
147
+ var m = ge();
148
+ return y(m, () => s.label), S((h) => {
149
+ var E = /^\d+$/.test(s.label), L = o().x, M = o().y - 6;
150
+ return E !== h.e && l(m, "data-count", h.e = E), L !== h.t && l(m, "x", h.t = L), M !== h.a && l(m, "y", h.a = M), h;
151
+ }, {
152
+ e: void 0,
153
+ t: void 0,
154
+ a: void 0
155
+ }), m;
156
+ })()
157
+ }), u), u.$$keydown = (o) => j(f, o), u.$$contextmenu = (o) => R(f, o), u.$$click = (o) => {
158
+ o.stopPropagation(), i.onActivate?.(x(f, o.currentTarget, o));
159
+ }, u.addEventListener("blur", () => v(null)), u.addEventListener("focus", () => v(f)), u.addEventListener("pointerleave", () => v(null)), u.addEventListener("pointerenter", () => v(f)), S((o) => {
160
+ var m = s.id, h = Q().has(s.id), E = A(f), L = C(), M = C(), N = s.label;
161
+ return m !== o.e && l(k, "data-graph-object", o.e = m), h !== o.t && l(k, "data-emphasized", o.t = h), E !== o.a && l(k, "data-selected", o.a = E), L !== o.o && l(z, "d", o.o = L), M !== o.i && l(u, "d", o.i = M), N !== o.n && l(u, "aria-label", o.n = N), o;
147
162
  }, {
148
163
  e: void 0,
149
164
  t: void 0,
@@ -151,28 +166,28 @@ function me(i) {
151
166
  o: void 0,
152
167
  i: void 0,
153
168
  n: void 0
154
- }), v;
169
+ }), k;
155
170
  }
156
171
  });
157
172
  }
158
- }), null), C(() => c(l, "aria-label", i.ariaLabel)), l;
159
- })(), y(P, {
173
+ }), null), S(() => l(c, "aria-label", i.ariaLabel)), c;
174
+ })(), w(D, {
160
175
  get each() {
161
- return x();
176
+ return b();
162
177
  },
163
- children: j
178
+ children: G
164
179
  })];
165
180
  }
166
- }), null), w(e, () => i.overlay, null), C((r) => {
181
+ }), null), y(e, () => i.overlay, null), S((r) => {
167
182
  var a = `floe-graph ${i.class ?? ""}`, n = i.ariaLabel;
168
- return a !== r.e && N(e, r.e = a), n !== r.t && c(e, "aria-label", r.t = n), r;
183
+ return a !== r.e && V(e, r.e = a), n !== r.t && l(e, "aria-label", r.t = n), r;
169
184
  }, {
170
185
  e: void 0,
171
186
  t: void 0
172
187
  }), e;
173
188
  })();
174
189
  }
175
- p(["focusin", "focusout", "click", "contextmenu", "keydown"]);
190
+ te(["focusin", "focusout", "click", "contextmenu", "keydown"]);
176
191
  export {
177
- me as GraphCanvas
192
+ ke as GraphCanvas
178
193
  };
@@ -6,3 +6,5 @@ export declare function fitGraphViewport(bounds: GraphBounds, size: {
6
6
  }, padding?: number): GraphViewport;
7
7
  /** Includes descendants so highlighting a group traces all of its direct routes. */
8
8
  export declare function graphRelatedEdges(layout: GraphLayout, nodeId: string): ReadonlySet<string>;
9
+ /** Put the short edge label on its longest routed segment, away from arrowheads. */
10
+ export declare function graphEdgeLabelPosition(sections: readonly (readonly GraphPoint[])[]): GraphPoint | null;
@@ -1,35 +1,45 @@
1
- function c(t) {
2
- return t.map((h, a) => `${a ? "L" : "M"}${h.x},${h.y}`).join(" ");
1
+ function c(e) {
2
+ return e.map((n, h) => `${h ? "L" : "M"}${n.x},${n.y}`).join(" ");
3
3
  }
4
- function o(t, h, a = 48) {
5
- const i = Math.max(
4
+ function s(e, n, h = 48) {
5
+ const a = Math.max(
6
6
  0.1,
7
7
  Math.min(
8
8
  1,
9
- (h.width - a * 2) / Math.max(1, t.width),
10
- (h.height - a * 2) / Math.max(1, t.height)
9
+ (n.width - h * 2) / Math.max(1, e.width),
10
+ (n.height - h * 2) / Math.max(1, e.height)
11
11
  )
12
12
  );
13
13
  return {
14
- x: (h.width - t.width * i) / 2 - t.x * i,
15
- y: (h.height - t.height * i) / 2 - t.y * i,
16
- scale: i
14
+ x: (n.width - e.width * a) / 2 - e.x * a,
15
+ y: (n.height - e.height * a) / 2 - e.y * a,
16
+ scale: a
17
17
  };
18
18
  }
19
- function f(t, h) {
20
- const a = /* @__PURE__ */ new Set([h]), i = /* @__PURE__ */ new Map();
21
- for (const e of t.nodes)
22
- e.parentId && i.set(e.parentId, [...i.get(e.parentId) ?? [], e.id]);
23
- const n = (e) => {
24
- for (const r of i.get(e) ?? [])
25
- a.has(r) || (a.add(r), n(r));
19
+ function f(e, n) {
20
+ const h = /* @__PURE__ */ new Set([n]), a = /* @__PURE__ */ new Map();
21
+ for (const t of e.nodes)
22
+ t.parentId && a.set(t.parentId, [...a.get(t.parentId) ?? [], t.id]);
23
+ const r = (t) => {
24
+ for (const i of a.get(t) ?? [])
25
+ h.has(i) || (h.add(i), r(i));
26
26
  };
27
- return n(h), new Set(
28
- t.edges.filter((e) => a.has(e.source) || a.has(e.target)).map((e) => e.id)
27
+ return r(n), new Set(
28
+ e.edges.filter((t) => h.has(t.source) || h.has(t.target)).map((t) => t.id)
29
29
  );
30
30
  }
31
+ function g(e) {
32
+ let n = null, h = 0;
33
+ for (const a of e)
34
+ for (let r = 1; r < a.length; r++) {
35
+ const t = a[r - 1], i = a[r], o = Math.abs(i.x - t.x) + Math.abs(i.y - t.y);
36
+ o > h && (h = o, n = { x: (t.x + i.x) / 2, y: (t.y + i.y) / 2 });
37
+ }
38
+ return n;
39
+ }
31
40
  export {
32
- o as fitGraphViewport,
41
+ s as fitGraphViewport,
42
+ g as graphEdgeLabelPosition,
33
43
  f as graphRelatedEdges,
34
44
  c as graphSectionPath
35
45
  };
@@ -1,47 +1,48 @@
1
- function k(n) {
2
- const i = /* @__PURE__ */ new Set(), p = (e) => {
3
- if (!e || i.has(e)) throw new Error(`Duplicate or empty graph ID: ${e}`);
4
- i.add(e);
5
- }, s = new Map(n.nodes.map((e) => [e.id, e]));
6
- for (const e of n.nodes) {
7
- if (p(e.id), ![e.width, e.height].every((r) => Number.isFinite(r) && r > 0))
8
- throw new Error(`Invalid dimensions for graph node: ${e.id}`);
9
- for (const r of e.ports ?? []) p(r.id);
10
- const a = /* @__PURE__ */ new Set([e.id]);
11
- let d = e.parentId;
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;
12
13
  for (; d !== void 0; ) {
13
14
  const r = s.get(d);
14
15
  if (!r || r.kind !== "group")
15
- throw new Error(`Invalid parent for graph node: ${e.id}`);
16
- if (a.has(d)) throw new Error(`Cyclic graph containment: ${e.id}`);
16
+ throw new Error(`Invalid parent for graph node: ${t.id}`);
17
+ if (a.has(d)) throw new Error(`Cyclic graph containment: ${t.id}`);
17
18
  a.add(d), d = r.parentId;
18
19
  }
19
20
  }
20
- for (const e of n.edges) {
21
- p(e.id);
21
+ for (const t of i.edges) {
22
+ p(t.id);
22
23
  for (const [a, d] of [
23
- [e.source, e.sourcePort],
24
- [e.target, e.targetPort]
24
+ [t.source, t.sourcePort],
25
+ [t.target, t.targetPort]
25
26
  ]) {
26
27
  const r = s.get(a);
27
28
  if (!r || d !== void 0 && !r.ports?.some((c) => c.id === d))
28
- throw new Error(`Invalid endpoint for graph edge: ${e.id}`);
29
+ throw new Error(`Invalid endpoint for graph edge: ${t.id}`);
29
30
  }
30
31
  }
31
32
  }
32
- async function N(n, i, p) {
33
- k(n);
34
- const s = i.groupPadding ?? { top: 64, right: 28, bottom: 28, left: 28 };
35
- if (![...Object.values(s), i.spacing ?? 64].every((t) => Number.isFinite(t) && t >= 0))
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))
36
37
  throw new Error("Graph layout spacing must be finite and nonnegative");
37
- const e = /* @__PURE__ */ new Map();
38
- for (const t of n.nodes)
39
- e.set(t.id, {
40
- id: t.id,
41
- width: t.width,
42
- height: t.height,
43
- ...t.kind === "group" ? { children: [] } : {},
44
- ports: t.ports?.map((o) => ({
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) => ({
45
46
  id: o.id,
46
47
  width: 1,
47
48
  height: 1,
@@ -53,35 +54,35 @@ async function N(n, i, p) {
53
54
  }
54
55
  });
55
56
  const a = [];
56
- for (const t of n.nodes)
57
- (t.parentId ? e.get(t.parentId).children : a).push(e.get(t.id));
57
+ for (const e of i.nodes)
58
+ (e.parentId ? t.get(e.parentId).children : a).push(t.get(e.id));
58
59
  const d = /* @__PURE__ */ new Set([
59
- ...n.nodes.flatMap((t) => [t.id, ...(t.ports ?? []).map((o) => o.id)]),
60
- ...n.edges.map((t) => t.id)
60
+ ...i.nodes.flatMap((e) => [e.id, ...(e.ports ?? []).map((o) => o.id)]),
61
+ ...i.edges.map((e) => e.id)
61
62
  ]);
62
63
  let r = "$graph";
63
64
  for (; d.has(r); ) r += "$";
64
65
  const c = await p.layout({
65
66
  id: r,
66
67
  children: a,
67
- edges: n.edges.map((t) => ({
68
- id: t.id,
69
- sources: [t.sourcePort ?? t.source],
70
- targets: [t.targetPort ?? t.target]
68
+ edges: i.edges.map((e) => ({
69
+ id: e.id,
70
+ sources: [e.sourcePort ?? e.source],
71
+ targets: [e.targetPort ?? e.target]
71
72
  })),
72
73
  layoutOptions: {
73
74
  "elk.algorithm": "layered",
74
- "elk.direction": i.direction ?? "RIGHT",
75
+ "elk.direction": n.direction ?? "RIGHT",
75
76
  "elk.edgeRouting": "ORTHOGONAL",
76
77
  "elk.hierarchyHandling": "INCLUDE_CHILDREN",
77
- "elk.spacing.nodeNode": String(i.spacing ?? 64),
78
- "elk.layered.spacing.nodeNodeBetweenLayers": String(i.spacing ?? 64),
78
+ "elk.spacing.nodeNode": String(n.spacing ?? 64),
79
+ "elk.layered.spacing.nodeNodeBetweenLayers": String(n.spacing ?? 64),
79
80
  "elk.layered.considerModelOrder.strategy": "NODES_AND_EDGES",
80
81
  "elk.randomSeed": "1"
81
82
  }
82
- }), f = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), I = (t) => {
83
- for (const o of t.edges ?? []) {
84
- const h = o.container ?? t.id, l = f.get(h) ?? { x: 0, y: 0 };
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 };
85
86
  x.set(
86
87
  o.id,
87
88
  (o.sections ?? []).map(
@@ -92,30 +93,34 @@ async function N(n, i, p) {
92
93
  )
93
94
  );
94
95
  }
95
- for (const o of t.children ?? []) I(o);
96
- }, E = (t, o, h) => {
97
- const l = o + (t.x ?? 0), g = h + (t.y ?? 0);
98
- f.set(t.id, { x: l, y: g, width: t.width ?? 0, height: t.height ?? 0 });
99
- for (const w of t.children ?? []) E(w, l, g);
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);
100
101
  };
101
- for (const t of c.children ?? []) E(t, 0, 0);
102
+ for (const e of c.children ?? []) E(e, 0, 0);
102
103
  I(c);
103
- const y = i.anchor && f.get(i.anchor.nodeId), u = y ? i.anchor.position.x - y.x : 0, m = y ? i.anchor.position.y - y.y : 0;
104
- return {
105
- nodes: n.nodes.map((t) => {
106
- const o = f.get(t.id);
107
- return { ...t, ...o, x: o.x + u, y: o.y + m };
108
- }),
109
- edges: n.edges.map((t) => ({
110
- ...t,
111
- sections: (x.get(t.id) ?? []).map(
112
- (o) => o.map((h) => ({ x: h.x + u, y: h.y + m }))
113
- )
114
- })),
115
- bounds: { x: u, y: m, width: c.width ?? 0, height: c.height ?? 0 }
116
- };
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 };
107
+ });
108
+ return v(
109
+ {
110
+ 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 }))
115
+ )
116
+ })),
117
+ bounds: { x: m, y: u, width: c.width ?? 0, height: c.height ?? 0 }
118
+ },
119
+ n,
120
+ i.nodes
121
+ );
117
122
  }
118
123
  export {
119
- N as computeGraphLayout,
120
- k as validateGraphInput
124
+ O as computeGraphLayout,
125
+ $ as validateGraphInput
121
126
  };
@@ -0,0 +1,3 @@
1
+ import type { GraphLayout, GraphLayoutOptions, GraphNode } from './types';
2
+ /** Apply explicit fixed or preferred positions, then route the resulting geometry once. */
3
+ export declare function applyGraphPositions(layout: GraphLayout, options: GraphLayoutOptions, input: readonly GraphNode[]): GraphLayout;
@@ -0,0 +1,169 @@
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
8
+ );
9
+ function A(e, n, v) {
10
+ if (v.some((h) => N(e, h) || N(n, h)))
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;
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;
32
+ }
33
+ y[c] = t;
34
+ }
35
+ return h;
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);
50
+ });
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
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) }));
62
+ }
63
+ }
64
+ throw new Error("Pinned graph positions cannot be routed within the layout budget");
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))
71
+ throw new Error(`Invalid graph position: ${t.nodeId}`);
72
+ I.set(t.nodeId, t);
73
+ }
74
+ const w = /* @__PURE__ */ new Map();
75
+ for (const t of r.values())
76
+ if (t.parentId) {
77
+ const c = w.get(t.parentId) ?? [];
78
+ c.push(t), w.set(t.parentId, c);
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))
88
+ throw new Error(`Pinned child lies outside group content: ${t.id}`);
89
+ const f = Math.max(
90
+ t.x + t.width,
91
+ ...s.map((l) => l.x + l.width + M.right)
92
+ ), m = Math.max(
93
+ t.y + t.height,
94
+ ...s.map((l) => l.y + l.height + M.bottom)
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;
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)
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);
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
129
+ );
130
+ }, x = [...r.values()].filter((s) => !s.parentId);
131
+ for (const s of x) d(s);
132
+ p(x);
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 }
146
+ ] : [
147
+ { x: i.x + i.width, y: u.y },
148
+ { x: i.x + i.width + 8, y: u.y }
149
+ ];
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));
156
+ return {
157
+ nodes: E,
158
+ edges: y,
159
+ 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
+ }
165
+ };
166
+ }
167
+ export {
168
+ F as applyGraphPositions
169
+ };
@@ -46,6 +46,12 @@ export interface GraphLayout {
46
46
  bounds: GraphBounds;
47
47
  }
48
48
  export interface GraphLayoutOptions {
49
+ /** Absolute world positions. Descendants move with their group. Invalid positions always fail. */
50
+ positions?: readonly (GraphPoint & {
51
+ nodeId: string;
52
+ })[];
53
+ /** Fixed (default) rejects impossible geometry. Preferred retains clear positions and separates colliding siblings, resizing groups around their content before routing. */
54
+ positionMode?: 'fixed' | 'preferred';
49
55
  direction?: 'RIGHT' | 'DOWN' | 'LEFT' | 'UP';
50
56
  spacing?: number;
51
57
  groupPadding?: {
@@ -1,6 +1,6 @@
1
1
  import { createComponent as n, insert as l, addEventListener as v, effect as C, setAttribute as F, Portal as d, memo as P, template as c, delegateEvents as L } from "solid-js/web";
2
2
  import { createMemo as R, createEffect as f, onCleanup as _, Show as s } from "solid-js";
3
- import { Motion as w } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.15/node_modules/solid-motionone/dist/index.js";
3
+ import { Motion as w } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.17/node_modules/solid-motionone/dist/index.js";
4
4
  import { easing as B, duration as k } from "../../utils/animations.js";
5
5
  import { useOverlayMask as K } from "../../hooks/useOverlayMask.js";
6
6
  import { X as Z } from "../icons/index.js";
@@ -1,6 +1,6 @@
1
1
  import { insert as m, createComponent as d, effect as K, setAttribute as I, memo as B, className as He, template as $, Dynamic as Ke, Portal as We, setStyleProperty as Ne, use as Ve, delegateEvents as Ge } from "solid-js/web";
2
2
  import { createSignal as de, onCleanup as p, createEffect as ee, createMemo as A, Show as R, For as te, Index as Ue } from "solid-js";
3
- import { Motion as W } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.15/node_modules/solid-motionone/dist/index.js";
3
+ import { Motion as W } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.17/node_modules/solid-motionone/dist/index.js";
4
4
  import { easing as N, duration as V } from "../../utils/animations.js";
5
5
  import { Plus as qe } from "../icons/index.js";
6
6
  import { startHotInteraction as ze } from "../../utils/hotInteraction.js";
@@ -1,5 +1,5 @@
1
1
  import { insert as n, createComponent as c, memo as s, effect as d, setAttribute as u, template as k, delegateEvents as v } from "solid-js/web";
2
- import { Motion as m } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.15/node_modules/solid-motionone/dist/index.js";
2
+ import { Motion as m } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.17/node_modules/solid-motionone/dist/index.js";
3
3
  import { easing as f, duration as h } from "../../utils/animations.js";
4
4
  import { Lock as g, Unlock as _ } from "../icons/index.js";
5
5
  var L = /* @__PURE__ */ k("<button type=button class=workbench-lock-button data-floe-surface=floating data-floe-canvas-interactive=true><span class=workbench-lock-button__icon>"), w = /* @__PURE__ */ k("<span class=workbench-lock-button__kbd>");
@@ -1,6 +1,6 @@
1
1
  import { createComponent as r, insert as l, template as s, delegateEvents as y } from "solid-js/web";
2
2
  import { Show as f } from "solid-js";
3
- import { Motion as i } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.15/node_modules/solid-motionone/dist/index.js";
3
+ import { Motion as i } from "../../node_modules/.pnpm/solid-motionone@1.0.4_solid-js@1.9.17/node_modules/solid-motionone/dist/index.js";
4
4
  import { easing as h, duration as c } from "../../utils/animations.js";
5
5
  import { useOverlayMask as b } from "../../hooks/useOverlayMask.js";
6
6
  import { X as v } from "../icons/index.js";
package/dist/graph.css CHANGED
@@ -91,3 +91,21 @@
91
91
  outline-color: Highlight;
92
92
  }
93
93
  }
94
+
95
+ .floe-graph__edge-label {
96
+ fill: var(--graph-edge, var(--muted-foreground));
97
+ stroke: var(--graph-background, var(--background));
98
+ stroke-width: 3px;
99
+ paint-order: stroke fill;
100
+ font: 11px var(--font-mono, monospace);
101
+ text-anchor: middle;
102
+ pointer-events: none;
103
+ opacity: 0;
104
+ }
105
+ .floe-graph__edge-label[data-count='true'] {
106
+ opacity: 0.7;
107
+ }
108
+ .floe-graph__edges [data-emphasized='true'] .floe-graph__edge-label,
109
+ .floe-graph__edges [data-selected='true'] .floe-graph__edge-label {
110
+ opacity: 1;
111
+ }
package/dist/graph.js CHANGED
@@ -1,10 +1,11 @@
1
- import { fitGraphViewport as e, graphRelatedEdges as t, graphSectionPath as o } from "./components/graph/geometry.js";
2
- import { createGraphLayoutEngine as h } from "./components/graph/engine.js";
3
- import { GraphCanvas as g } from "./components/graph/GraphCanvas.js";
1
+ import { fitGraphViewport as e, graphEdgeLabelPosition as o, graphRelatedEdges as t, graphSectionPath as p } from "./components/graph/geometry.js";
2
+ import { createGraphLayoutEngine as g } from "./components/graph/engine.js";
3
+ import { GraphCanvas as n } from "./components/graph/GraphCanvas.js";
4
4
  export {
5
- g as GraphCanvas,
6
- h as createGraphLayoutEngine,
5
+ n as GraphCanvas,
6
+ g as createGraphLayoutEngine,
7
7
  e as fitGraphViewport,
8
+ o as graphEdgeLabelPosition,
8
9
  t as graphRelatedEdges,
9
- o as graphSectionPath
10
+ p as graphSectionPath
10
11
  };
@@ -1,8 +1,8 @@
1
1
  import { createComponent as m, mergeProps as v, Dynamic as x } from "solid-js/web";
2
2
  import { createSignal as p, createContext as d, splitProps as P, useContext as l, createEffect as u, onCleanup as S, batch as c } from "solid-js";
3
- import { resolveFirst as E } from "../../../../@solid-primitives_refs@1.1.4_solid-js@1.9.15/node_modules/@solid-primitives/refs/dist/index.js";
4
- import { createSwitchTransition as y } from "../../../../@solid-primitives_transition-group@1.1.2_solid-js@1.9.15/node_modules/@solid-primitives/transition-group/dist/index.js";
5
- import { combineStyle as C } from "../../../../@solid-primitives_props@3.2.4_solid-js@1.9.15/node_modules/@solid-primitives/props/dist/combineProps.js";
3
+ import { resolveFirst as E } from "../../../../@solid-primitives_refs@1.1.4_solid-js@1.9.17/node_modules/@solid-primitives/refs/dist/index.js";
4
+ import { createSwitchTransition as y } from "../../../../@solid-primitives_transition-group@1.1.2_solid-js@1.9.17/node_modules/@solid-primitives/transition-group/dist/index.js";
5
+ import { combineStyle as C } from "../../../../@solid-primitives_props@3.2.4_solid-js@1.9.17/node_modules/@solid-primitives/props/dist/combineProps.js";
6
6
  import { createMotionState as h, mountedStates as M } from "../../../../@motionone_dom@10.18.0/node_modules/@motionone/dom/dist/state/index.es.js";
7
7
  import { createStyles as T } from "../../../../@motionone_dom@10.18.0/node_modules/@motionone/dom/dist/animate/utils/style-object.es.js";
8
8
  var g = d(), D = (t) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/floe-webapp-core",
3
- "version": "0.83.1",
3
+ "version": "0.85.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -156,7 +156,7 @@
156
156
  "clean": "rm -rf dist *.tsbuildinfo"
157
157
  },
158
158
  "peerDependencies": {
159
- "solid-js": "^1.8.0"
159
+ "solid-js": "^1.9.17"
160
160
  },
161
161
  "dependencies": {
162
162
  "clsx": "^2.1.1",
@@ -173,7 +173,7 @@
173
173
  },
174
174
  "devDependencies": {
175
175
  "@tailwindcss/vite": "^4.3.3",
176
- "solid-js": "^1.9.15",
176
+ "solid-js": "^1.9.17",
177
177
  "tailwindcss": "^4.3.3",
178
178
  "typescript": "^5.9.3",
179
179
  "vite": "^7.3.6",