@agent-ui-kit/web-components 0.0.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.
- package/dist/agent-ui.css +1 -0
- package/dist/chunks/agent-ciCayeod.js +1241 -0
- package/dist/chunks/agent-ciCayeod.js.map +1 -0
- package/dist/chunks/registry-BNb5ABBs.js +25 -0
- package/dist/chunks/registry-BNb5ABBs.js.map +1 -0
- package/dist/components/agent.js +13 -0
- package/dist/components/agent.js.map +1 -0
- package/dist/components/editor.js +200 -0
- package/dist/components/editor.js.map +1 -0
- package/dist/components/graph.js +352 -0
- package/dist/components/graph.js.map +1 -0
- package/dist/components.js +3137 -0
- package/dist/components.js.map +1 -0
- package/dist/element.js +10 -0
- package/dist/element.js.map +1 -0
- package/dist/icons.js +104 -0
- package/dist/icons.js.map +1 -0
- package/dist/reactivity.js +9 -0
- package/dist/reactivity.js.map +1 -0
- package/dist/register.js +1441 -0
- package/dist/register.js.map +1 -0
- package/dist/store.js +34 -0
- package/dist/store.js.map +1 -0
- package/dist/styles.js +2 -0
- package/dist/styles.js.map +1 -0
- package/dist/traits.js +2453 -0
- package/dist/traits.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { AuiEditor as E, AuiEditorLayer as S } from "./editor.js";
|
|
2
|
+
import { A as f } from "../chunks/agent-ciCayeod.js";
|
|
3
|
+
const w = "http://www.w3.org/2000/svg";
|
|
4
|
+
class N extends E {
|
|
5
|
+
static attributes = {
|
|
6
|
+
...E.attributes,
|
|
7
|
+
"snap-to-grid": { type: "boolean", default: !1 },
|
|
8
|
+
connectable: { type: "boolean", default: !1 }
|
|
9
|
+
};
|
|
10
|
+
#t = null;
|
|
11
|
+
#e = "";
|
|
12
|
+
#i = "";
|
|
13
|
+
#s = "";
|
|
14
|
+
activate() {
|
|
15
|
+
this.hasAttribute("background") || this.setAttribute("background", "dots"), super.activate(), this.addEventListener("aui:port-drag-start", this.#r);
|
|
16
|
+
}
|
|
17
|
+
dispose() {
|
|
18
|
+
this.removeEventListener("aui:port-drag-start", this.#r), this.#a(), super.dispose();
|
|
19
|
+
}
|
|
20
|
+
// ── Drag-to-connect ──
|
|
21
|
+
#r = (t) => {
|
|
22
|
+
if (!this.connectable) return;
|
|
23
|
+
const { portId: e, side: h, position: o } = t.detail, a = t.target.closest("aui-graph-node");
|
|
24
|
+
if (!a) return;
|
|
25
|
+
const s = a.getAttribute("node-id") ?? "";
|
|
26
|
+
this.#e = s, this.#i = e, this.#s = h;
|
|
27
|
+
const r = this.querySelector(
|
|
28
|
+
'aui-graph-layer[name="wires"] svg[data-editor-svg], aui-editor-layer[name="under"] svg[data-editor-svg]'
|
|
29
|
+
);
|
|
30
|
+
if (!r) return;
|
|
31
|
+
this.#t = document.createElementNS(w, "path"), this.#t.setAttribute("fill", "none"), this.#t.style.stroke = "var(--aui-accent)", this.#t.setAttribute("stroke-width", "2"), this.#t.setAttribute("stroke-dasharray", "6 4"), this.#t.setAttribute("data-graph-drag-noodle", ""), r.appendChild(this.#t);
|
|
32
|
+
const i = o, n = (u) => {
|
|
33
|
+
if (!this.#t) return;
|
|
34
|
+
const l = this.screenToEditor(u.clientX, u.clientY), p = this.#n(i, l, h);
|
|
35
|
+
this.#t.setAttribute("d", p);
|
|
36
|
+
}, d = (u) => {
|
|
37
|
+
document.removeEventListener("pointermove", n), document.removeEventListener("pointerup", d);
|
|
38
|
+
const l = this.#o(u.clientX, u.clientY);
|
|
39
|
+
if (this.#a(), !l) return;
|
|
40
|
+
const p = l.closest("aui-graph-node");
|
|
41
|
+
if (!p) return;
|
|
42
|
+
const g = p.getAttribute("node-id") ?? "", m = l.getAttribute("port-id") ?? "";
|
|
43
|
+
if (g === s && m === e) return;
|
|
44
|
+
const y = `${s}:${e}`, A = `${g}:${m}`, x = this.querySelector('aui-graph-layer[name="wires"]');
|
|
45
|
+
if (x) {
|
|
46
|
+
const b = document.createElement("aui-graph-noodle");
|
|
47
|
+
b.setAttribute("from", y), b.setAttribute("to", A), b.setAttribute("color", "accent"), b.setAttribute("weight", "2"), x.appendChild(b);
|
|
48
|
+
}
|
|
49
|
+
this.dispatchEvent(new CustomEvent("aui:noodle-connect", {
|
|
50
|
+
bubbles: !0,
|
|
51
|
+
composed: !0,
|
|
52
|
+
detail: { from: y, to: A, fromNode: s, fromPort: e, toNode: g, toPort: m }
|
|
53
|
+
}));
|
|
54
|
+
};
|
|
55
|
+
document.addEventListener("pointermove", n), document.addEventListener("pointerup", d);
|
|
56
|
+
};
|
|
57
|
+
#n(t, e, h) {
|
|
58
|
+
const o = Math.max(Math.abs(e.x - t.x), Math.abs(e.y - t.y)), a = Math.max(50, o * 0.5);
|
|
59
|
+
let s = t.x, r = t.y;
|
|
60
|
+
switch (h) {
|
|
61
|
+
case "right":
|
|
62
|
+
s = t.x + a;
|
|
63
|
+
break;
|
|
64
|
+
case "left":
|
|
65
|
+
s = t.x - a;
|
|
66
|
+
break;
|
|
67
|
+
case "bottom":
|
|
68
|
+
r = t.y + a;
|
|
69
|
+
break;
|
|
70
|
+
case "top":
|
|
71
|
+
r = t.y - a;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
return `M ${t.x},${t.y} C ${s},${r} ${e.x},${e.y} ${e.x},${e.y}`;
|
|
75
|
+
}
|
|
76
|
+
#o(t, e) {
|
|
77
|
+
let o = null, a = 30;
|
|
78
|
+
for (const s of this.querySelectorAll("aui-graph-port")) {
|
|
79
|
+
const r = s.getBoundingClientRect(), i = r.left + r.width / 2, n = r.top + r.height / 2, d = Math.hypot(t - i, e - n);
|
|
80
|
+
d < a && (a = d, o = s);
|
|
81
|
+
}
|
|
82
|
+
return o;
|
|
83
|
+
}
|
|
84
|
+
#a() {
|
|
85
|
+
this.#t?.remove(), this.#t = null, this.#e = "", this.#i = "", this.#s = "";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
class $ extends S {
|
|
89
|
+
}
|
|
90
|
+
class k extends f {
|
|
91
|
+
static attributes = {
|
|
92
|
+
x: { type: "string", default: "0" },
|
|
93
|
+
y: { type: "string", default: "0" },
|
|
94
|
+
"node-id": { type: "string", default: "" },
|
|
95
|
+
selected: { type: "boolean", default: !1 }
|
|
96
|
+
};
|
|
97
|
+
// Drag state
|
|
98
|
+
#t = !1;
|
|
99
|
+
#e = 0;
|
|
100
|
+
#i = 0;
|
|
101
|
+
#s = 0;
|
|
102
|
+
#r = 0;
|
|
103
|
+
get xValue() {
|
|
104
|
+
return Number(this.x) || 0;
|
|
105
|
+
}
|
|
106
|
+
get yValue() {
|
|
107
|
+
return Number(this.y) || 0;
|
|
108
|
+
}
|
|
109
|
+
// ── Lifecycle ──
|
|
110
|
+
activate() {
|
|
111
|
+
this.#n(), this.addEventListener("pointerdown", this.#o), this.addEventListener("pointermove", this.#a), this.addEventListener("pointerup", this.#h), this.addEventListener("pointercancel", this.#h), this.addEffect(() => {
|
|
112
|
+
this.x, this.y, this.#n();
|
|
113
|
+
}), this.addEffect(() => {
|
|
114
|
+
this.selected ? this.setAttribute("data-graph-selected", "") : this.removeAttribute("data-graph-selected");
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
dispose() {
|
|
118
|
+
this.removeEventListener("pointerdown", this.#o), this.removeEventListener("pointermove", this.#a), this.removeEventListener("pointerup", this.#h), this.removeEventListener("pointercancel", this.#h);
|
|
119
|
+
}
|
|
120
|
+
// ── Position ──
|
|
121
|
+
#n() {
|
|
122
|
+
this.style.transform = `translate(${this.xValue}px, ${this.yValue}px)`;
|
|
123
|
+
}
|
|
124
|
+
// ── Drag handlers ──
|
|
125
|
+
#o = (t) => {
|
|
126
|
+
t.button !== 0 || this.closest("aui-graph-ui, aui-editor")?.hasAttribute("data-editor-space") || t.target.closest("aui-graph-port") || (t.stopPropagation(), this.#t = !0, this.#e = t.clientX, this.#i = t.clientY, this.#s = this.xValue, this.#r = this.yValue, this.setPointerCapture(t.pointerId), this.setAttribute("data-graph-dragging", ""));
|
|
127
|
+
};
|
|
128
|
+
#a = (t) => {
|
|
129
|
+
if (!this.#t) return;
|
|
130
|
+
const e = this.closest("aui-graph-ui, aui-editor"), h = e?.zoomLevel ?? 1, o = (t.clientX - this.#e) / h, a = (t.clientY - this.#i) / h;
|
|
131
|
+
let s = this.#s + o, r = this.#r + a;
|
|
132
|
+
if (e?.["snap-to-grid"]) {
|
|
133
|
+
const i = e.gridSizeValue ?? 24;
|
|
134
|
+
s = Math.round(s / i) * i, r = Math.round(r / i) * i;
|
|
135
|
+
}
|
|
136
|
+
this.x = String(Math.round(s)), this.y = String(Math.round(r)), this.#n();
|
|
137
|
+
};
|
|
138
|
+
#h = (t) => {
|
|
139
|
+
this.#t && (this.#t = !1, this.removeAttribute("data-graph-dragging"), this.dispatchEvent(new CustomEvent("aui:node-move", {
|
|
140
|
+
bubbles: !0,
|
|
141
|
+
composed: !0,
|
|
142
|
+
detail: {
|
|
143
|
+
id: this["node-id"],
|
|
144
|
+
x: this.xValue,
|
|
145
|
+
y: this.yValue
|
|
146
|
+
}
|
|
147
|
+
})));
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const c = "http://www.w3.org/2000/svg", P = {
|
|
151
|
+
accent: "var(--aui-accent)",
|
|
152
|
+
success: "var(--aui-success)",
|
|
153
|
+
warning: "var(--aui-warning)",
|
|
154
|
+
danger: "var(--aui-danger)",
|
|
155
|
+
muted: "var(--aui-border-muted)",
|
|
156
|
+
scrim: "var(--aui-ink-muted)"
|
|
157
|
+
};
|
|
158
|
+
class M extends f {
|
|
159
|
+
static attributes = {
|
|
160
|
+
from: { type: "string", default: "" },
|
|
161
|
+
to: { type: "string", default: "" },
|
|
162
|
+
color: { type: "string", default: "muted" },
|
|
163
|
+
weight: { type: "string", default: "2" },
|
|
164
|
+
label: { type: "string", default: "" },
|
|
165
|
+
"label-bg": { type: "string", default: "var(--aui-doc)" },
|
|
166
|
+
animation: { type: "enum", values: ["none", "stream", "blob"], default: "none" },
|
|
167
|
+
"animate-direction": { type: "enum", values: ["forward", "reverse"], default: "forward" },
|
|
168
|
+
"animate-speed": { type: "string", default: "1500" },
|
|
169
|
+
dashed: { type: "boolean", default: !1 }
|
|
170
|
+
};
|
|
171
|
+
#t = null;
|
|
172
|
+
#e = null;
|
|
173
|
+
#i = null;
|
|
174
|
+
#s = null;
|
|
175
|
+
#r = null;
|
|
176
|
+
#n = null;
|
|
177
|
+
#o = null;
|
|
178
|
+
#a = null;
|
|
179
|
+
#h = 0;
|
|
180
|
+
// ── Lifecycle ──
|
|
181
|
+
activate() {
|
|
182
|
+
requestAnimationFrame(() => {
|
|
183
|
+
this.#m();
|
|
184
|
+
}), this.addEffect(() => {
|
|
185
|
+
this.from, this.to, this.color, this.weight, this.label, this["label-bg"], this.animation, this["animate-direction"], this["animate-speed"], this.dashed, this.#d();
|
|
186
|
+
});
|
|
187
|
+
const t = this.closest("aui-graph-ui, aui-editor");
|
|
188
|
+
t && (this.#a = new MutationObserver(() => this.#p()), this.#a.observe(t, {
|
|
189
|
+
attributes: !0,
|
|
190
|
+
attributeFilter: ["style", "x", "y", "translate"],
|
|
191
|
+
subtree: !0
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
dispose() {
|
|
195
|
+
this.#a?.disconnect(), this.#a = null, cancelAnimationFrame(this.#h), this.#t?.remove(), this.#t = null, this.#e = null, this.#i = null, this.#s = null, this.#r = null, this.#n = null, this.#o = null;
|
|
196
|
+
}
|
|
197
|
+
#p() {
|
|
198
|
+
cancelAnimationFrame(this.#h), this.#h = requestAnimationFrame(() => this.#d());
|
|
199
|
+
}
|
|
200
|
+
/** Resolve a color attribute to a CSS value. Named presets are mapped; raw values pass through. */
|
|
201
|
+
get resolvedColor() {
|
|
202
|
+
const t = this.color;
|
|
203
|
+
return P[t] ?? t;
|
|
204
|
+
}
|
|
205
|
+
// ── Rendering ──
|
|
206
|
+
#g() {
|
|
207
|
+
const t = this.closest("aui-graph-layer, aui-editor-layer");
|
|
208
|
+
return t ? t.querySelector("svg[data-editor-svg]") : this.closest("svg");
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Resolve an endpoint value to a point + port side.
|
|
212
|
+
* Formats:
|
|
213
|
+
* "x,y" — literal coordinates, defaults to inferred side
|
|
214
|
+
* "nodeId:portId" — resolves from live port element position
|
|
215
|
+
*/
|
|
216
|
+
#u(t, e) {
|
|
217
|
+
if (!t) return null;
|
|
218
|
+
if (/^-?[\d.]+\s*,\s*-?[\d.]+$/.test(t)) {
|
|
219
|
+
const o = t.split(","), a = Number(o[0].trim()), s = Number(o[1].trim());
|
|
220
|
+
if (!isNaN(a) && !isNaN(s)) return { x: a, y: s, side: e };
|
|
221
|
+
}
|
|
222
|
+
const h = t.indexOf(":");
|
|
223
|
+
if (h > 0) {
|
|
224
|
+
const o = t.slice(0, h), a = t.slice(h + 1), s = this.closest("aui-graph-ui, aui-editor");
|
|
225
|
+
if (!s) return null;
|
|
226
|
+
const r = s.querySelector(`aui-graph-node[node-id="${CSS.escape(o)}"]`);
|
|
227
|
+
if (!r) return null;
|
|
228
|
+
const i = r.querySelector(`aui-graph-port[port-id="${CSS.escape(a)}"]`);
|
|
229
|
+
if (!i?.getPosition) return null;
|
|
230
|
+
const n = i.getPosition(), d = i.getAttribute("side") ?? e;
|
|
231
|
+
return { x: n.x, y: n.y, side: d };
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
#m() {
|
|
236
|
+
const t = this.#g();
|
|
237
|
+
if (!t) return;
|
|
238
|
+
this.#t = document.createElementNS(c, "g"), this.#t.setAttribute("data-graph-noodle", ""), this.#e = document.createElementNS(c, "path"), this.#e.setAttribute("fill", "none"), this.#e.addEventListener("click", this.#c), this.#t.appendChild(this.#e);
|
|
239
|
+
const e = document.createElementNS(c, "path");
|
|
240
|
+
e.setAttribute("fill", "none"), e.setAttribute("stroke", "transparent"), e.setAttribute("stroke-width", "12"), e.setAttribute("data-graph-noodle-hit", ""), e.addEventListener("click", this.#c), this.#t.appendChild(e), t.appendChild(this.#t), this.#d();
|
|
241
|
+
}
|
|
242
|
+
/** Compute a control point that extends away from the port in its natural direction */
|
|
243
|
+
#l(t, e, h, o) {
|
|
244
|
+
switch (h) {
|
|
245
|
+
case "right":
|
|
246
|
+
return [t + o, e];
|
|
247
|
+
case "left":
|
|
248
|
+
return [t - o, e];
|
|
249
|
+
case "bottom":
|
|
250
|
+
return [t, e + o];
|
|
251
|
+
case "top":
|
|
252
|
+
return [t, e - o];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
#d() {
|
|
256
|
+
if (!this.#t || !this.#e) return;
|
|
257
|
+
const t = this.#u(this.from, "right"), e = this.#u(this.to, "left");
|
|
258
|
+
if (!t || !e) return;
|
|
259
|
+
const h = Math.max(Math.abs(e.x - t.x), Math.abs(e.y - t.y)), o = Math.max(50, h * 0.5), [a, s] = this.#l(t.x, t.y, t.side, o), [r, i] = this.#l(e.x, e.y, e.side, o), n = `M ${t.x},${t.y} C ${a},${s} ${r},${i} ${e.x},${e.y}`, d = this.resolvedColor;
|
|
260
|
+
this.#e.setAttribute("d", n), this.#t.style.color = d, this.#e.style.stroke = "currentColor", this.#e.setAttribute("stroke-width", this.weight), this.dashed ? this.#e.setAttribute("stroke-dasharray", "6 4") : this.#e.removeAttribute("stroke-dasharray");
|
|
261
|
+
const u = this.#t.querySelector("[data-graph-noodle-hit]");
|
|
262
|
+
if (u && u.setAttribute("d", n), this.animation === "stream") {
|
|
263
|
+
this.#e.setAttribute("stroke-dasharray", "8 4"), this.#e.setAttribute("data-graph-noodle-stream", "");
|
|
264
|
+
const l = Number(this["animate-speed"]) || 1500, p = this["animate-direction"] === "reverse" ? "reverse" : "normal";
|
|
265
|
+
this.#e.style.animationDuration = `${l}ms`, this.#e.style.animationDirection = p;
|
|
266
|
+
} else
|
|
267
|
+
this.#e.removeAttribute("data-graph-noodle-stream"), this.dashed || this.#e.removeAttribute("stroke-dasharray");
|
|
268
|
+
this.#b(n), this.#v(t, e, a, s, r, i);
|
|
269
|
+
}
|
|
270
|
+
#b(t) {
|
|
271
|
+
if (this.animation === "blob") {
|
|
272
|
+
this.#n || (this.#n = document.createElementNS(c, "circle"), this.#n.setAttribute("r", "4"), this.#n.setAttribute("data-graph-noodle-blob", ""), this.#o = document.createElementNS(c, "animateMotion"), this.#o.setAttribute("repeatCount", "indefinite"), this.#n.appendChild(this.#o), this.#t.appendChild(this.#n)), this.#n.style.fill = "currentColor";
|
|
273
|
+
const e = Number(this["animate-speed"]) || 1500;
|
|
274
|
+
this.#o.setAttribute("dur", `${e}ms`), this.#o.setAttribute("path", t), this["animate-direction"] === "reverse" ? (this.#o.setAttribute("keyPoints", "1;0"), this.#o.setAttribute("keyTimes", "0;1")) : (this.#o.removeAttribute("keyPoints"), this.#o.removeAttribute("keyTimes"));
|
|
275
|
+
} else this.#n && (this.#n.remove(), this.#n = null, this.#o = null);
|
|
276
|
+
}
|
|
277
|
+
#v(t, e, h, o, a, s) {
|
|
278
|
+
const r = this.label;
|
|
279
|
+
if (r) {
|
|
280
|
+
this.#i || (this.#i = document.createElementNS(c, "g"), this.#i.setAttribute("data-graph-noodle-label", ""), this.#r = document.createElementNS(c, "rect"), this.#r.setAttribute("rx", "3"), this.#r.setAttribute("ry", "3"), this.#i.appendChild(this.#r), this.#s = document.createElementNS(c, "text"), this.#s.setAttribute("text-anchor", "middle"), this.#s.setAttribute("dominant-baseline", "central"), this.#i.appendChild(this.#s), this.#t.appendChild(this.#i));
|
|
281
|
+
const i = 0.5, n = 1 - i, d = n * n * n * t.x + 3 * n * n * i * h + 3 * n * i * i * a + i * i * i * e.x, u = n * n * n * t.y + 3 * n * n * i * o + 3 * n * i * i * s + i * i * i * e.y;
|
|
282
|
+
this.#s.textContent = r, this.#s.setAttribute("x", String(d)), this.#s.setAttribute("y", String(u));
|
|
283
|
+
const l = 6, g = r.length * 7, m = 16;
|
|
284
|
+
this.#r.setAttribute("x", String(d - g / 2 - l)), this.#r.setAttribute("y", String(u - m / 2 - 2)), this.#r.setAttribute("width", String(g + l * 2)), this.#r.setAttribute("height", String(m + 4)), this.#r.setAttribute("fill", this["label-bg"]);
|
|
285
|
+
} else this.#i && (this.#i.remove(), this.#i = null, this.#s = null, this.#r = null);
|
|
286
|
+
}
|
|
287
|
+
#c = () => {
|
|
288
|
+
this.dispatchEvent(new CustomEvent("aui:noodle-click", {
|
|
289
|
+
bubbles: !0,
|
|
290
|
+
composed: !0,
|
|
291
|
+
detail: { from: this.from, to: this.to }
|
|
292
|
+
}));
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
class I extends f {
|
|
296
|
+
static attributes = {
|
|
297
|
+
"port-id": { type: "string", default: "" },
|
|
298
|
+
side: { type: "enum", values: ["top", "right", "bottom", "left"], default: "right" },
|
|
299
|
+
type: { type: "enum", values: ["input", "output", "bidirectional"], default: "bidirectional" },
|
|
300
|
+
"data-type": { type: "string", default: "any" },
|
|
301
|
+
connected: { type: "boolean", default: !1 }
|
|
302
|
+
};
|
|
303
|
+
#t = null;
|
|
304
|
+
/** Get the center position of this port in graph coordinates */
|
|
305
|
+
getPosition() {
|
|
306
|
+
const t = this.getBoundingClientRect(), e = this.closest("aui-graph-ui, aui-editor");
|
|
307
|
+
return e?.screenToEditor ? e.screenToEditor(
|
|
308
|
+
t.left + t.width / 2,
|
|
309
|
+
t.top + t.height / 2
|
|
310
|
+
) : {
|
|
311
|
+
x: t.left + t.width / 2,
|
|
312
|
+
y: t.top + t.height / 2
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
// ── Lifecycle ──
|
|
316
|
+
activate() {
|
|
317
|
+
this.#t = document.createElement("div"), this.#t.setAttribute("data-graph-port-dot", ""), this.appendChild(this.#t), this.addEventListener("pointerdown", this.#e), this.addEventListener("pointerenter", this.#i), this.addEventListener("pointerleave", this.#s), this.addEffect(() => {
|
|
318
|
+
this.connected ? this.setAttribute("data-graph-port-connected", "") : this.removeAttribute("data-graph-port-connected");
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
dispose() {
|
|
322
|
+
this.removeEventListener("pointerdown", this.#e), this.removeEventListener("pointerenter", this.#i), this.removeEventListener("pointerleave", this.#s);
|
|
323
|
+
}
|
|
324
|
+
// ── Handlers ──
|
|
325
|
+
#e = (t) => {
|
|
326
|
+
t.button === 0 && (t.stopPropagation(), this.dispatchEvent(new CustomEvent("aui:port-drag-start", {
|
|
327
|
+
bubbles: !0,
|
|
328
|
+
composed: !0,
|
|
329
|
+
detail: {
|
|
330
|
+
portId: this["port-id"],
|
|
331
|
+
side: this.side,
|
|
332
|
+
type: this.type,
|
|
333
|
+
dataType: this["data-type"],
|
|
334
|
+
position: this.getPosition()
|
|
335
|
+
}
|
|
336
|
+
})));
|
|
337
|
+
};
|
|
338
|
+
#i = () => {
|
|
339
|
+
this.setAttribute("data-graph-port-hover", "");
|
|
340
|
+
};
|
|
341
|
+
#s = () => {
|
|
342
|
+
this.removeAttribute("data-graph-port-hover");
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
export {
|
|
346
|
+
$ as AuiGraphLayer,
|
|
347
|
+
k as AuiGraphNode,
|
|
348
|
+
M as AuiGraphNoodle,
|
|
349
|
+
I as AuiGraphPort,
|
|
350
|
+
N as AuiGraphUi
|
|
351
|
+
};
|
|
352
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sources":["../../src/components/graph/graph-ui.ts","../../src/components/graph/graph-layer.ts","../../src/components/graph/graph-node.ts","../../src/components/graph/graph-noodle.ts","../../src/components/graph/graph-port.ts"],"sourcesContent":["// ── aui-graph-ui ────────────────────────────────────────────\n//\n// Graph editor canvas. Extends aui-editor with graph-specific\n// features: dot grid background, snap-to-grid, and interactive\n// drag-to-connect between ports.\n//\n// @attr {string} grid-size - Dot grid spacing in px (default: \"24\")\n// @attr {boolean} snap-to-grid - Snap nodes to grid when dragged\n// @attr {boolean} connectable - Enable drag-to-connect between ports\n// @fires aui:noodle-connect - A new connection was created via drag\n\nimport { AuiEditor } from '../editor/editor.ts'\nimport type { AttributeSchema } from '#element'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\nexport class AuiGraphUi extends AuiEditor {\n static override attributes: AttributeSchema = {\n ...AuiEditor.attributes!,\n 'snap-to-grid': { type: 'boolean', default: false },\n connectable: { type: 'boolean', default: false },\n }\n\n declare 'snap-to-grid': boolean\n declare connectable: boolean\n\n #dragPath: SVGPathElement | null = null\n #dragSourceNode: string = ''\n #dragSourcePort: string = ''\n #dragSourceSide: string = ''\n\n protected override activate(): void {\n if (!this.hasAttribute('background')) {\n this.setAttribute('background', 'dots')\n }\n super.activate()\n\n // Drag-to-connect: listen for port drag events\n this.addEventListener('aui:port-drag-start', this.#onPortDragStart as EventListener)\n }\n\n protected override dispose(): void {\n this.removeEventListener('aui:port-drag-start', this.#onPortDragStart as EventListener)\n this.#cleanupDrag()\n super.dispose()\n }\n\n // ── Drag-to-connect ──\n\n #onPortDragStart = (e: CustomEvent): void => {\n if (!this.connectable) return\n\n const { portId, side, position } = e.detail\n const node = (e.target as HTMLElement).closest('aui-graph-node')\n if (!node) return\n\n const nodeId = node.getAttribute('node-id') ?? ''\n this.#dragSourceNode = nodeId\n this.#dragSourcePort = portId\n this.#dragSourceSide = side\n\n // Find or create the SVG in the wire layer\n const wireLayer = this.querySelector(\n 'aui-graph-layer[name=\"wires\"] svg[data-editor-svg], aui-editor-layer[name=\"under\"] svg[data-editor-svg]'\n ) as SVGSVGElement | null\n if (!wireLayer) return\n\n // Create temporary drag path\n this.#dragPath = document.createElementNS(SVG_NS, 'path')\n this.#dragPath.setAttribute('fill', 'none')\n this.#dragPath.style.stroke = 'var(--aui-accent)'\n this.#dragPath.setAttribute('stroke-width', '2')\n this.#dragPath.setAttribute('stroke-dasharray', '6 4')\n this.#dragPath.setAttribute('data-graph-drag-noodle', '')\n wireLayer.appendChild(this.#dragPath)\n\n const startPos = position as { x: number; y: number }\n\n const onPointerMove = (me: PointerEvent) => {\n if (!this.#dragPath) return\n const editorPos = this.screenToEditor(me.clientX, me.clientY)\n const d = this.#computeDragPath(startPos, editorPos, side)\n this.#dragPath.setAttribute('d', d)\n }\n\n const onPointerUp = (ue: PointerEvent) => {\n document.removeEventListener('pointermove', onPointerMove)\n document.removeEventListener('pointerup', onPointerUp)\n\n // Find target port under pointer\n const targetPort = this.#findPortAt(ue.clientX, ue.clientY)\n this.#cleanupDrag()\n\n if (!targetPort) return\n\n const targetNode = targetPort.closest('aui-graph-node')\n if (!targetNode) return\n\n const targetNodeId = targetNode.getAttribute('node-id') ?? ''\n const targetPortId = targetPort.getAttribute('port-id') ?? ''\n\n // Don't connect to self\n if (targetNodeId === nodeId && targetPortId === portId) return\n\n const from = `${nodeId}:${portId}`\n const to = `${targetNodeId}:${targetPortId}`\n\n // Stamp a noodle into the wire layer\n const wireLayer = this.querySelector('aui-graph-layer[name=\"wires\"]')\n if (wireLayer) {\n const noodle = document.createElement('aui-graph-noodle')\n noodle.setAttribute('from', from)\n noodle.setAttribute('to', to)\n noodle.setAttribute('color', 'accent')\n noodle.setAttribute('weight', '2')\n wireLayer.appendChild(noodle)\n }\n\n this.dispatchEvent(new CustomEvent('aui:noodle-connect', {\n bubbles: true, composed: true,\n detail: { from, to, fromNode: nodeId, fromPort: portId, toNode: targetNodeId, toPort: targetPortId },\n }))\n }\n\n document.addEventListener('pointermove', onPointerMove)\n document.addEventListener('pointerup', onPointerUp)\n }\n\n #computeDragPath(\n p1: { x: number; y: number },\n p2: { x: number; y: number },\n side: string,\n ): string {\n const dist = Math.max(Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y))\n const offset = Math.max(50, dist * 0.5)\n\n let cx1 = p1.x, cy1 = p1.y\n switch (side) {\n case 'right': cx1 = p1.x + offset; break\n case 'left': cx1 = p1.x - offset; break\n case 'bottom': cy1 = p1.y + offset; break\n case 'top': cy1 = p1.y - offset; break\n }\n\n return `M ${p1.x},${p1.y} C ${cx1},${cy1} ${p2.x},${p2.y} ${p2.x},${p2.y}`\n }\n\n #findPortAt(clientX: number, clientY: number): HTMLElement | null {\n const SNAP_RADIUS = 30\n let nearest: HTMLElement | null = null\n let minDist = SNAP_RADIUS\n\n for (const port of this.querySelectorAll('aui-graph-port')) {\n const rect = port.getBoundingClientRect()\n const cx = rect.left + rect.width / 2\n const cy = rect.top + rect.height / 2\n const dist = Math.hypot(clientX - cx, clientY - cy)\n if (dist < minDist) {\n minDist = dist\n nearest = port as HTMLElement\n }\n }\n\n return nearest\n }\n\n #cleanupDrag(): void {\n this.#dragPath?.remove()\n this.#dragPath = null\n this.#dragSourceNode = ''\n this.#dragSourcePort = ''\n this.#dragSourceSide = ''\n }\n}\n","// ── aui-graph-layer ─────────────────────────────────────────\n//\n// Graph stacking layer. Extends aui-editor-layer — backward-\n// compatible alias with the same API. Keeps the aui-graph-layer\n// tag name so existing markup works unchanged.\n//\n// @attr {string} name - Layer name (e.g., \"wires\", \"content\", \"chrome\")\n// @attr {string} type - \"html\" or \"svg\" (default: \"html\")\n\nimport { AuiEditorLayer } from '../editor/editor-layer.ts'\n\nexport class AuiGraphLayer extends AuiEditorLayer {}\n","// ── aui-graph-node ──────────────────────────────────────────\n//\n// A draggable container at specific graph coordinates.\n// Children can be any AgentUI components. Positioned via\n// CSS transform: translate(x, y).\n//\n// @attr {string} x - Horizontal position in graph space (default: \"0\")\n// @attr {string} y - Vertical position in graph space (default: \"0\")\n// @attr {string} node-id - Unique identifier for this node\n// @attr {boolean} selected - Whether this node is selected\n// @fires aui:node-move - Node was dragged. Detail: `{ id, x, y }`\n\nimport { AgentElement } from '#element'\nimport type { AttributeSchema } from '#element'\n\nexport class AuiGraphNode extends AgentElement {\n static override attributes: AttributeSchema = {\n x: { type: 'string', default: '0' },\n y: { type: 'string', default: '0' },\n 'node-id': { type: 'string', default: '' },\n selected: { type: 'boolean', default: false },\n }\n\n declare x: string\n declare y: string\n declare 'node-id': string\n declare selected: boolean\n\n // Drag state\n #dragging = false\n #dragStartX = 0\n #dragStartY = 0\n #dragOriginX = 0\n #dragOriginY = 0\n\n get xValue(): number { return Number(this.x) || 0 }\n get yValue(): number { return Number(this.y) || 0 }\n\n // ── Lifecycle ──\n\n protected override activate(): void {\n this.#applyPosition()\n\n this.addEventListener('pointerdown', this.#onPointerDown)\n this.addEventListener('pointermove', this.#onPointerMove)\n this.addEventListener('pointerup', this.#onPointerUp)\n this.addEventListener('pointercancel', this.#onPointerUp)\n\n // Reactive: sync position when attributes change\n this.addEffect(() => {\n void this.x\n void this.y\n this.#applyPosition()\n })\n\n // Reactive: sync selected data attribute\n this.addEffect(() => {\n if (this.selected) {\n this.setAttribute('data-graph-selected', '')\n } else {\n this.removeAttribute('data-graph-selected')\n }\n })\n }\n\n protected override dispose(): void {\n this.removeEventListener('pointerdown', this.#onPointerDown)\n this.removeEventListener('pointermove', this.#onPointerMove)\n this.removeEventListener('pointerup', this.#onPointerUp)\n this.removeEventListener('pointercancel', this.#onPointerUp)\n }\n\n // ── Position ──\n\n #applyPosition(): void {\n this.style.transform = `translate(${this.xValue}px, ${this.yValue}px)`\n }\n\n // ── Drag handlers ──\n\n #onPointerDown = (e: PointerEvent): void => {\n if (e.button !== 0) return\n\n // Check if parent graph is in space-pan mode\n const graph = this.closest('aui-graph-ui, aui-editor')\n if (graph?.hasAttribute('data-editor-space')) return\n\n // Don't start drag from ports\n if ((e.target as HTMLElement).closest('aui-graph-port')) return\n\n e.stopPropagation()\n this.#dragging = true\n this.#dragStartX = e.clientX\n this.#dragStartY = e.clientY\n this.#dragOriginX = this.xValue\n this.#dragOriginY = this.yValue\n\n this.setPointerCapture(e.pointerId)\n this.setAttribute('data-graph-dragging', '')\n }\n\n #onPointerMove = (e: PointerEvent): void => {\n if (!this.#dragging) return\n\n const graph = this.closest('aui-graph-ui, aui-editor') as any\n const zoom = graph?.zoomLevel ?? 1\n\n const dx = (e.clientX - this.#dragStartX) / zoom\n const dy = (e.clientY - this.#dragStartY) / zoom\n\n let newX = this.#dragOriginX + dx\n let newY = this.#dragOriginY + dy\n\n // Snap to grid if enabled\n if (graph?.['snap-to-grid']) {\n const gs = graph.gridSizeValue ?? 24\n newX = Math.round(newX / gs) * gs\n newY = Math.round(newY / gs) * gs\n }\n\n this.x = String(Math.round(newX))\n this.y = String(Math.round(newY))\n this.#applyPosition()\n }\n\n #onPointerUp = (_e: PointerEvent): void => {\n if (!this.#dragging) return\n this.#dragging = false\n this.removeAttribute('data-graph-dragging')\n\n this.dispatchEvent(new CustomEvent('aui:node-move', {\n bubbles: true, composed: true,\n detail: {\n id: this['node-id'],\n x: this.xValue,\n y: this.yValue,\n },\n }))\n }\n}\n","// ── aui-graph-noodle ────────────────────────────────────────\n//\n// SVG cubic bezier path connecting two points or ports.\n// Rendered inside an SVG graph-layer.\n//\n// @attr {string} from - Port selector or \"x,y\" coordinates\n// @attr {string} to - Port selector or \"x,y\" coordinates\n// @attr {string} color - Named preset or CSS color (default: \"var(--aui-border)\")\n// Presets: \"accent\" | \"success\" | \"warning\" | \"danger\" | \"muted\" | \"scrim\"\n// @attr {string} weight - Stroke width (default: \"2\")\n// @attr {string} label - Text shown at midpoint\n// @attr {string} label-bg - Label background (default: \"var(--aui-doc)\")\n// @attr {string} animate - \"none\" | \"stream\" | \"blob\" (default: \"none\")\n// @attr {string} animate-direction - \"forward\" | \"reverse\" (default: \"forward\")\n// @attr {string} animate-speed - Duration in ms (default: \"1500\")\n// @attr {boolean} dashed - Dashed stroke\n// @fires aui:noodle-click - Noodle path was clicked\n\nimport { AgentElement } from '#element'\nimport type { AttributeSchema } from '#element'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\ntype PortSide = 'top' | 'right' | 'bottom' | 'left'\n\ninterface ResolvedPoint {\n x: number\n y: number\n side: PortSide\n}\n\n/** Named color presets mapped to CSS custom properties */\nconst COLOR_PRESETS: Record<string, string> = {\n accent: 'var(--aui-accent)',\n success: 'var(--aui-success)',\n warning: 'var(--aui-warning)',\n danger: 'var(--aui-danger)',\n muted: 'var(--aui-border-muted)',\n scrim: 'var(--aui-ink-muted)',\n}\n\nexport class AuiGraphNoodle extends AgentElement {\n static override attributes: AttributeSchema = {\n from: { type: 'string', default: '' },\n to: { type: 'string', default: '' },\n color: { type: 'string', default: 'muted' },\n weight: { type: 'string', default: '2' },\n label: { type: 'string', default: '' },\n 'label-bg': { type: 'string', default: 'var(--aui-doc)' },\n animation: { type: 'enum', values: ['none', 'stream', 'blob'] as const, default: 'none' },\n 'animate-direction': { type: 'enum', values: ['forward', 'reverse'] as const, default: 'forward' },\n 'animate-speed': { type: 'string', default: '1500' },\n dashed: { type: 'boolean', default: false },\n }\n\n declare from: string\n declare to: string\n declare color: string\n declare weight: string\n declare label: string\n declare 'label-bg': string\n declare animation: string\n declare 'animate-direction': string\n declare 'animate-speed': string\n declare dashed: boolean\n\n #group: SVGGElement | null = null\n #path: SVGPathElement | null = null\n #labelGroup: SVGGElement | null = null\n #labelText: SVGTextElement | null = null\n #labelRect: SVGRectElement | null = null\n #blob: SVGCircleElement | null = null\n #animateMotion: SVGAnimateMotionElement | null = null\n #observer: MutationObserver | null = null\n #rafId = 0\n\n // ── Lifecycle ──\n\n protected override activate(): void {\n // Defer initial render to next frame so nodes have been positioned\n requestAnimationFrame(() => {\n this.#render()\n })\n\n // Reactive: re-render on attribute changes\n this.addEffect(() => {\n // Subscribe to all relevant signals\n void this.from\n void this.to\n void this.color\n void this.weight\n void this.label\n void this['label-bg']\n void this.animation\n void this['animate-direction']\n void this['animate-speed']\n void this.dashed\n this.#update()\n })\n\n // Observe node movements so noodles track port positions\n const graphUi = this.closest('aui-graph-ui, aui-editor')\n if (graphUi) {\n this.#observer = new MutationObserver(() => this.#queueUpdate())\n this.#observer.observe(graphUi, {\n attributes: true,\n attributeFilter: ['style', 'x', 'y', 'translate'],\n subtree: true,\n })\n }\n }\n\n protected override dispose(): void {\n this.#observer?.disconnect()\n this.#observer = null\n cancelAnimationFrame(this.#rafId)\n this.#group?.remove()\n this.#group = null\n this.#path = null\n this.#labelGroup = null\n this.#labelText = null\n this.#labelRect = null\n this.#blob = null\n this.#animateMotion = null\n }\n\n #queueUpdate(): void {\n cancelAnimationFrame(this.#rafId)\n this.#rafId = requestAnimationFrame(() => this.#update())\n }\n\n /** Resolve a color attribute to a CSS value. Named presets are mapped; raw values pass through. */\n get resolvedColor(): string {\n const raw = this.color\n return COLOR_PRESETS[raw] ?? raw\n }\n\n // ── Rendering ──\n\n #getSvg(): SVGSVGElement | null {\n // Find the parent layer's SVG (supports both editor and graph layers)\n const layer = this.closest('aui-graph-layer, aui-editor-layer')\n if (layer) {\n return layer.querySelector('svg[data-editor-svg]')\n }\n // Fallback: find any parent SVG\n return this.closest('svg')\n }\n\n /**\n * Resolve an endpoint value to a point + port side.\n * Formats:\n * \"x,y\" — literal coordinates, defaults to inferred side\n * \"nodeId:portId\" — resolves from live port element position\n */\n #resolveEndpoint(value: string, fallbackSide: PortSide): ResolvedPoint | null {\n if (!value) return null\n\n // Try \"x,y\" format\n if (/^-?[\\d.]+\\s*,\\s*-?[\\d.]+$/.test(value)) {\n const parts = value.split(',')\n const x = Number(parts[0].trim())\n const y = Number(parts[1].trim())\n if (!isNaN(x) && !isNaN(y)) return { x, y, side: fallbackSide }\n }\n\n // Port selector: \"nodeId:portId\"\n const colonIdx = value.indexOf(':')\n if (colonIdx > 0) {\n const nodeId = value.slice(0, colonIdx)\n const portId = value.slice(colonIdx + 1)\n const graphUi = this.closest('aui-graph-ui, aui-editor')\n if (!graphUi) return null\n\n const node = graphUi.querySelector(`aui-graph-node[node-id=\"${CSS.escape(nodeId)}\"]`)\n if (!node) return null\n\n const port = node.querySelector(`aui-graph-port[port-id=\"${CSS.escape(portId)}\"]`) as any\n if (!port?.getPosition) return null\n\n const pos = port.getPosition()\n const side = (port.getAttribute('side') ?? fallbackSide) as PortSide\n return { x: pos.x, y: pos.y, side }\n }\n\n return null\n }\n\n #render(): void {\n const svg = this.#getSvg()\n if (!svg) return\n\n // Create group\n this.#group = document.createElementNS(SVG_NS, 'g')\n this.#group.setAttribute('data-graph-noodle', '')\n\n // Create path\n this.#path = document.createElementNS(SVG_NS, 'path')\n this.#path.setAttribute('fill', 'none')\n this.#path.addEventListener('click', this.#onClick)\n this.#group.appendChild(this.#path)\n\n // Create hit area (wider invisible path for easier clicking)\n const hitPath = document.createElementNS(SVG_NS, 'path')\n hitPath.setAttribute('fill', 'none')\n hitPath.setAttribute('stroke', 'transparent')\n hitPath.setAttribute('stroke-width', '12')\n hitPath.setAttribute('data-graph-noodle-hit', '')\n hitPath.addEventListener('click', this.#onClick)\n this.#group.appendChild(hitPath)\n\n svg.appendChild(this.#group)\n this.#update()\n }\n\n /** Compute a control point that extends away from the port in its natural direction */\n #controlPoint(x: number, y: number, side: PortSide, offset: number): [number, number] {\n switch (side) {\n case 'right': return [x + offset, y]\n case 'left': return [x - offset, y]\n case 'bottom': return [x, y + offset]\n case 'top': return [x, y - offset]\n }\n }\n\n #update(): void {\n if (!this.#group || !this.#path) return\n\n const p1 = this.#resolveEndpoint(this.from, 'right')\n const p2 = this.#resolveEndpoint(this.to, 'left')\n if (!p1 || !p2) return\n\n // Direction-aware cubic bezier control points\n const dist = Math.max(Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y))\n const offset = Math.max(50, dist * 0.5)\n\n const [cx1, cy1] = this.#controlPoint(p1.x, p1.y, p1.side, offset)\n const [cx2, cy2] = this.#controlPoint(p2.x, p2.y, p2.side, offset)\n\n const d = `M ${p1.x},${p1.y} C ${cx1},${cy1} ${cx2},${cy2} ${p2.x},${p2.y}`\n\n // Update main path — set color on group, use currentColor for stroke\n const stroke = this.resolvedColor\n this.#path.setAttribute('d', d)\n this.#group.style.color = stroke\n this.#path.style.stroke = 'currentColor'\n this.#path.setAttribute('stroke-width', this.weight)\n\n if (this.dashed) {\n this.#path.setAttribute('stroke-dasharray', '6 4')\n } else {\n this.#path.removeAttribute('stroke-dasharray')\n }\n\n // Update hit area path\n const hitPath = this.#group.querySelector('[data-graph-noodle-hit]')\n if (hitPath) {\n hitPath.setAttribute('d', d)\n }\n\n // Stream animation\n if (this.animation === 'stream') {\n this.#path.setAttribute('stroke-dasharray', '8 4')\n this.#path.setAttribute('data-graph-noodle-stream', '')\n\n const speed = Number(this['animate-speed']) || 1500\n const direction = this['animate-direction'] === 'reverse' ? 'reverse' : 'normal'\n\n this.#path.style.animationDuration = `${speed}ms`\n this.#path.style.animationDirection = direction\n } else {\n this.#path.removeAttribute('data-graph-noodle-stream')\n if (!this.dashed) {\n this.#path.removeAttribute('stroke-dasharray')\n }\n }\n\n // Blob animation\n this.#updateBlob(d)\n\n // Label\n this.#updateLabel(p1, p2, cx1, cy1, cx2, cy2)\n }\n\n #updateBlob(d: string): void {\n if (this.animation === 'blob') {\n if (!this.#blob) {\n this.#blob = document.createElementNS(SVG_NS, 'circle')\n this.#blob.setAttribute('r', '4')\n this.#blob.setAttribute('data-graph-noodle-blob', '')\n\n this.#animateMotion = document.createElementNS(SVG_NS, 'animateMotion') as SVGAnimateMotionElement\n this.#animateMotion.setAttribute('repeatCount', 'indefinite')\n this.#blob.appendChild(this.#animateMotion)\n this.#group!.appendChild(this.#blob)\n }\n\n this.#blob.style.fill = 'currentColor'\n\n const speed = Number(this['animate-speed']) || 1500\n this.#animateMotion!.setAttribute('dur', `${speed}ms`)\n this.#animateMotion!.setAttribute('path', d)\n\n if (this['animate-direction'] === 'reverse') {\n this.#animateMotion!.setAttribute('keyPoints', '1;0')\n this.#animateMotion!.setAttribute('keyTimes', '0;1')\n } else {\n this.#animateMotion!.removeAttribute('keyPoints')\n this.#animateMotion!.removeAttribute('keyTimes')\n }\n } else if (this.#blob) {\n this.#blob.remove()\n this.#blob = null\n this.#animateMotion = null\n }\n }\n\n #updateLabel(\n p1: { x: number; y: number },\n p2: { x: number; y: number },\n cx1: number, cy1: number,\n cx2: number, cy2: number,\n ): void {\n const labelText = this.label\n\n if (labelText) {\n if (!this.#labelGroup) {\n this.#labelGroup = document.createElementNS(SVG_NS, 'g')\n this.#labelGroup.setAttribute('data-graph-noodle-label', '')\n\n this.#labelRect = document.createElementNS(SVG_NS, 'rect')\n this.#labelRect.setAttribute('rx', '3')\n this.#labelRect.setAttribute('ry', '3')\n this.#labelGroup.appendChild(this.#labelRect)\n\n this.#labelText = document.createElementNS(SVG_NS, 'text')\n this.#labelText.setAttribute('text-anchor', 'middle')\n this.#labelText.setAttribute('dominant-baseline', 'central')\n this.#labelGroup.appendChild(this.#labelText)\n\n this.#group!.appendChild(this.#labelGroup)\n }\n\n // Midpoint of cubic bezier (t=0.5)\n const t = 0.5\n const mt = 1 - t\n const mx = mt * mt * mt * p1.x + 3 * mt * mt * t * cx1 + 3 * mt * t * t * cx2 + t * t * t * p2.x\n const my = mt * mt * mt * p1.y + 3 * mt * mt * t * cy1 + 3 * mt * t * t * cy2 + t * t * t * p2.y\n\n this.#labelText!.textContent = labelText\n this.#labelText!.setAttribute('x', String(mx))\n this.#labelText!.setAttribute('y', String(my))\n\n // Estimate text dimensions for background rect\n const padding = 6\n const charWidth = 7\n const textWidth = labelText.length * charWidth\n const textHeight = 16\n\n this.#labelRect!.setAttribute('x', String(mx - textWidth / 2 - padding))\n this.#labelRect!.setAttribute('y', String(my - textHeight / 2 - 2))\n this.#labelRect!.setAttribute('width', String(textWidth + padding * 2))\n this.#labelRect!.setAttribute('height', String(textHeight + 4))\n this.#labelRect!.setAttribute('fill', this['label-bg'])\n } else if (this.#labelGroup) {\n this.#labelGroup.remove()\n this.#labelGroup = null\n this.#labelText = null\n this.#labelRect = null\n }\n }\n\n #onClick = (): void => {\n this.dispatchEvent(new CustomEvent('aui:noodle-click', {\n bubbles: true, composed: true,\n detail: { from: this.from, to: this.to },\n }))\n }\n}\n","// ── aui-graph-port ──────────────────────────────────────────\n//\n// A connection endpoint on a graph node. Small circle on the\n// edge of the parent node that noodles connect to.\n//\n// @attr {string} port-id - Unique identifier within the parent node\n// @attr {string} side - \"top\" | \"right\" | \"bottom\" | \"left\"\n// @attr {string} type - \"input\" | \"output\" | \"bidirectional\" (default: \"bidirectional\")\n// @attr {string} data-type - For type checking connections (\"string\", \"number\", \"any\", etc.)\n// @attr {boolean} connected - Whether a noodle is connected to this port\n// @fires aui:port-connect - Port was connected\n// @fires aui:port-disconnect - Port was disconnected\n\nimport { AgentElement } from '#element'\nimport type { AttributeSchema } from '#element'\n\nexport class AuiGraphPort extends AgentElement {\n static override attributes: AttributeSchema = {\n 'port-id': { type: 'string', default: '' },\n side: { type: 'enum', values: ['top', 'right', 'bottom', 'left'] as const, default: 'right' },\n type: { type: 'enum', values: ['input', 'output', 'bidirectional'] as const, default: 'bidirectional' },\n 'data-type': { type: 'string', default: 'any' },\n connected: { type: 'boolean', default: false },\n }\n\n declare 'port-id': string\n declare side: string\n declare type: string\n declare 'data-type': string\n declare connected: boolean\n\n #dot: HTMLDivElement | null = null\n\n /** Get the center position of this port in graph coordinates */\n getPosition(): { x: number; y: number } {\n const rect = this.getBoundingClientRect()\n\n // Find the parent graph-ui to convert coordinates\n const graph = this.closest('aui-graph-ui, aui-editor') as any\n if (graph?.screenToEditor) {\n return graph.screenToEditor(\n rect.left + rect.width / 2,\n rect.top + rect.height / 2,\n )\n }\n\n // Fallback: just return the element center relative to viewport\n return {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n }\n }\n\n // ── Lifecycle ──\n\n protected override activate(): void {\n // Stamp the visual dot\n this.#dot = document.createElement('div')\n this.#dot.setAttribute('data-graph-port-dot', '')\n this.appendChild(this.#dot)\n\n // Wire drag-to-connect\n this.addEventListener('pointerdown', this.#onPointerDown)\n this.addEventListener('pointerenter', this.#onPointerEnter)\n this.addEventListener('pointerleave', this.#onPointerLeave)\n\n // Reactive: sync connected data attribute\n this.addEffect(() => {\n if (this.connected) {\n this.setAttribute('data-graph-port-connected', '')\n } else {\n this.removeAttribute('data-graph-port-connected')\n }\n })\n }\n\n protected override dispose(): void {\n this.removeEventListener('pointerdown', this.#onPointerDown)\n this.removeEventListener('pointerenter', this.#onPointerEnter)\n this.removeEventListener('pointerleave', this.#onPointerLeave)\n }\n\n // ── Handlers ──\n\n #onPointerDown = (e: PointerEvent): void => {\n if (e.button !== 0) return\n e.stopPropagation()\n\n // Dispatch event for parent graph to handle rubber-band noodle creation\n this.dispatchEvent(new CustomEvent('aui:port-drag-start', {\n bubbles: true, composed: true,\n detail: {\n portId: this['port-id'],\n side: this.side,\n type: this.type,\n dataType: this['data-type'],\n position: this.getPosition(),\n },\n }))\n }\n\n #onPointerEnter = (): void => {\n this.setAttribute('data-graph-port-hover', '')\n }\n\n #onPointerLeave = (): void => {\n this.removeAttribute('data-graph-port-hover')\n }\n}\n"],"names":["SVG_NS","AuiGraphUi","AuiEditor","#dragPath","#dragSourceNode","#dragSourcePort","#dragSourceSide","#onPortDragStart","#cleanupDrag","e","portId","side","position","node","nodeId","wireLayer","startPos","onPointerMove","me","editorPos","d","#computeDragPath","onPointerUp","ue","targetPort","#findPortAt","targetNode","targetNodeId","targetPortId","from","to","noodle","p1","p2","dist","offset","cx1","cy1","clientX","clientY","nearest","minDist","port","rect","cx","cy","AuiGraphLayer","AuiEditorLayer","AuiGraphNode","AgentElement","#dragging","#dragStartX","#dragStartY","#dragOriginX","#dragOriginY","#applyPosition","#onPointerDown","#onPointerMove","#onPointerUp","graph","zoom","dx","dy","newX","newY","gs","_e","COLOR_PRESETS","AuiGraphNoodle","#group","#path","#labelGroup","#labelText","#labelRect","#blob","#animateMotion","#observer","#rafId","#render","#update","graphUi","#queueUpdate","raw","#getSvg","layer","#resolveEndpoint","value","fallbackSide","parts","x","y","colonIdx","pos","svg","#onClick","hitPath","#controlPoint","cx2","cy2","stroke","speed","direction","#updateBlob","#updateLabel","labelText","t","mt","mx","my","padding","textWidth","textHeight","AuiGraphPort","#dot","#onPointerEnter","#onPointerLeave"],"mappings":"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"}
|