@stonecrop/node-editor 0.30.0 → 0.31.0
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/node-editor.d.ts +2 -0
- package/dist/node-editor.js +103 -101
- package/dist/node-editor.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/package.json +2 -2
- package/src/index.ts +5 -0
package/dist/node-editor.d.ts
CHANGED
package/dist/node-editor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { defineComponent as T, useTemplateRef as Y, ref as E, computed as M, openBlock as S, createElementBlock as P, Fragment as Q, createElementVNode as c, normalizeStyle as K, createVNode as O, unref as _, withCtx as R, withModifiers as D, toDisplayString as F, withDirectives as X, withKeys as W, vModelText as U, createCommentVNode as B, nextTick as
|
|
2
|
-
import { getBezierPath as ce, EdgeLabelRenderer as ee, Handle as q, useVueFlow as
|
|
1
|
+
import { defineComponent as T, useTemplateRef as Y, ref as E, computed as M, openBlock as S, createElementBlock as P, Fragment as Q, createElementVNode as c, normalizeStyle as K, createVNode as O, unref as _, withCtx as R, withModifiers as D, toDisplayString as F, withDirectives as X, withKeys as W, vModelText as U, createCommentVNode as B, nextTick as I, createBlock as H, onMounted as Z, onBeforeUnmount as ie, normalizeClass as ue, createTextVNode as re, mergeProps as A, useModel as J, mergeModels as de } from "vue";
|
|
2
|
+
import { getBezierPath as ce, EdgeLabelRenderer as ee, Handle as q, useVueFlow as fe, VueFlow as ve, Position as C } from "@vue-flow/core";
|
|
3
|
+
import { Position as He } from "@vue-flow/core";
|
|
3
4
|
import { Graph as pe, layout as ge } from "@dagrejs/dagre";
|
|
4
5
|
const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-label" }, he = {
|
|
5
6
|
key: 0,
|
|
@@ -42,18 +43,18 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
42
43
|
targetY: {}
|
|
43
44
|
},
|
|
44
45
|
emits: ["change", "remove"],
|
|
45
|
-
setup(l, { emit:
|
|
46
|
-
const
|
|
46
|
+
setup(l, { emit: f }) {
|
|
47
|
+
const d = l, p = f, n = Y("labelInput"), u = E(""), t = E(!1);
|
|
47
48
|
let e = 0;
|
|
48
49
|
const a = async () => {
|
|
49
|
-
let
|
|
50
|
-
|
|
50
|
+
let v = Date.now();
|
|
51
|
+
v - e < 500 && !t.value && await s(), e = v;
|
|
51
52
|
}, s = async () => {
|
|
52
|
-
u.value =
|
|
53
|
+
u.value = d.label, t.value = !0, await I(), n.value?.focus();
|
|
53
54
|
}, g = () => {
|
|
54
55
|
t.value = !1, p("change", u.value);
|
|
55
|
-
}, m = M(() => ce(
|
|
56
|
-
return (
|
|
56
|
+
}, m = M(() => ce(d));
|
|
57
|
+
return (v, y) => (S(), P(Q, null, [
|
|
57
58
|
c("path", {
|
|
58
59
|
d: m.value[0],
|
|
59
60
|
fill: "none",
|
|
@@ -78,7 +79,7 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
78
79
|
}),
|
|
79
80
|
class: "nodrag nopan editable-edge-label",
|
|
80
81
|
onClick: y[2] || (y[2] = (h) => a()),
|
|
81
|
-
onContextmenu: y[3] || (y[3] = D((h) =>
|
|
82
|
+
onContextmenu: y[3] || (y[3] = D((h) => v.$emit("remove", l.id), ["prevent"]))
|
|
82
83
|
}, [
|
|
83
84
|
c("div", ye, F(l.label), 1),
|
|
84
85
|
t.value ? (S(), P("div", he, [
|
|
@@ -125,27 +126,27 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
125
126
|
events: {}
|
|
126
127
|
},
|
|
127
128
|
emits: ["change"],
|
|
128
|
-
setup(l, { emit:
|
|
129
|
-
const
|
|
129
|
+
setup(l, { emit: f }) {
|
|
130
|
+
const d = l, p = f, n = Y("labelInput"), u = E(""), t = E(!1);
|
|
130
131
|
let e = 0;
|
|
131
132
|
const a = async () => {
|
|
132
133
|
let m = Date.now();
|
|
133
134
|
m - e < 500 && !t.value && await s(), e = m;
|
|
134
135
|
}, s = async () => {
|
|
135
|
-
u.value =
|
|
136
|
+
u.value = d.label, t.value = !0, await I(), n.value?.focus();
|
|
136
137
|
}, g = () => {
|
|
137
138
|
t.value = !1, p("change", u.value);
|
|
138
139
|
};
|
|
139
|
-
return (m,
|
|
140
|
-
onClick:
|
|
140
|
+
return (m, v) => (S(), P("div", {
|
|
141
|
+
onClick: v[2] || (v[2] = (y) => a())
|
|
141
142
|
}, [
|
|
142
143
|
c("div", null, F(l.label), 1),
|
|
143
144
|
t.value ? (S(), P("div", Se, [
|
|
144
145
|
X(c("input", {
|
|
145
146
|
ref: "labelInput",
|
|
146
|
-
"onUpdate:modelValue":
|
|
147
|
+
"onUpdate:modelValue": v[0] || (v[0] = (y) => u.value = y),
|
|
147
148
|
class: "label-input",
|
|
148
|
-
onBlur:
|
|
149
|
+
onBlur: v[1] || (v[1] = (y) => t.value = !1),
|
|
149
150
|
onKeypress: W(g, ["enter"])
|
|
150
151
|
}, null, 544), [
|
|
151
152
|
[U, u.value]
|
|
@@ -170,7 +171,7 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
170
171
|
class: "label-input-wrapper"
|
|
171
172
|
}, Be = {
|
|
172
173
|
inheritAttrs: !1
|
|
173
|
-
},
|
|
174
|
+
}, xe = /* @__PURE__ */ T({
|
|
174
175
|
...Be,
|
|
175
176
|
__name: "SelfLoopEdge",
|
|
176
177
|
props: {
|
|
@@ -206,17 +207,17 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
206
207
|
targetY: {}
|
|
207
208
|
},
|
|
208
209
|
emits: ["change", "remove"],
|
|
209
|
-
setup(l, { emit:
|
|
210
|
-
const
|
|
211
|
-
const { sourceX: h, sourceY: k, targetX: $, targetY:
|
|
210
|
+
setup(l, { emit: f }) {
|
|
211
|
+
const d = l, p = f, n = 90, u = 45, t = M(() => {
|
|
212
|
+
const { sourceX: h, sourceY: k, targetX: $, targetY: L } = d, j = `M ${h},${k} C ${h + u},${k - n} ${$ - u},${L - n} ${$},${L}`, z = (h + $) / 2, V = Math.min(k, L) - n * 0.72;
|
|
212
213
|
return { d: j, labelX: z, labelY: V };
|
|
213
214
|
}), e = Y("labelInput"), a = E(""), s = E(!1);
|
|
214
215
|
let g = 0;
|
|
215
216
|
const m = async () => {
|
|
216
217
|
let h = Date.now();
|
|
217
|
-
h - g < 500 && !s.value && await
|
|
218
|
-
},
|
|
219
|
-
a.value =
|
|
218
|
+
h - g < 500 && !s.value && await v(), g = h;
|
|
219
|
+
}, v = async () => {
|
|
220
|
+
a.value = d.label, s.value = !0, await I(), e.value?.focus();
|
|
220
221
|
}, y = () => {
|
|
221
222
|
s.value = !1, p("change", a.value);
|
|
222
223
|
};
|
|
@@ -266,13 +267,13 @@ const me = ["d"], be = ["id", "d", "marker-end"], ye = { class: "vue-flow__edge-
|
|
|
266
267
|
], 64));
|
|
267
268
|
}
|
|
268
269
|
});
|
|
269
|
-
function te(l,
|
|
270
|
-
const { rankdir:
|
|
270
|
+
function te(l, f = {}) {
|
|
271
|
+
const { rankdir: d = "LR", nodeWidth: p = 160, nodeHeight: n = 40, dimensions: u } = f, t = (s) => u?.[s] ?? { width: p, height: n }, e = [];
|
|
271
272
|
for (const s of l)
|
|
272
273
|
"source" in s || e.push(s.id);
|
|
273
274
|
if (e.length === 0) return [...l];
|
|
274
275
|
const a = new pe();
|
|
275
|
-
a.setGraph({ rankdir:
|
|
276
|
+
a.setGraph({ rankdir: d, nodesep: 40, ranksep: 80, edgesep: 20 }), a.setDefaultEdgeLabel(() => ({}));
|
|
276
277
|
for (const s of e) {
|
|
277
278
|
const { width: g, height: m } = t(s);
|
|
278
279
|
a.setNode(s, { width: g, height: m });
|
|
@@ -283,19 +284,19 @@ function te(l, v = {}) {
|
|
|
283
284
|
if ("source" in s) return s;
|
|
284
285
|
const g = a.node(s.id);
|
|
285
286
|
if (!g) return s;
|
|
286
|
-
const { width: m, height:
|
|
287
|
-
return { ...s, position: { x: g.x - m / 2, y: g.y -
|
|
287
|
+
const { width: m, height: v } = t(s.id);
|
|
288
|
+
return { ...s, position: { x: g.x - m / 2, y: g.y - v / 2 } };
|
|
288
289
|
});
|
|
289
290
|
}
|
|
290
|
-
const
|
|
291
|
+
const Ie = { class: "chart-controls" }, Le = { class: "chart-controls-left" }, Oe = { class: "chart-controls-right" }, Ve = { key: 0 }, Re = { key: 1 }, oe = /* @__PURE__ */ T({
|
|
291
292
|
__name: "NodeEditor",
|
|
292
293
|
props: {
|
|
293
294
|
modelValue: {},
|
|
294
295
|
nodeContainerClass: { type: [Boolean, null, String, Object, Array], default: "" }
|
|
295
296
|
},
|
|
296
297
|
emits: ["update:modelValue"],
|
|
297
|
-
setup(l, { emit:
|
|
298
|
-
const
|
|
298
|
+
setup(l, { emit: f }) {
|
|
299
|
+
const d = f, p = E(!1), n = E([]), u = E(), t = E(""), e = M(
|
|
299
300
|
() => n.value.findIndex((o) => o.id === t.value)
|
|
300
301
|
), a = M({
|
|
301
302
|
get: () => {
|
|
@@ -305,9 +306,9 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
305
306
|
return o;
|
|
306
307
|
},
|
|
307
308
|
set: (o) => {
|
|
308
|
-
|
|
309
|
+
d("update:modelValue", JSON.parse(JSON.stringify(o)));
|
|
309
310
|
}
|
|
310
|
-
}), { addEdges: s, removeEdges: g } =
|
|
311
|
+
}), { addEdges: s, removeEdges: g } = fe();
|
|
311
312
|
Z(() => {
|
|
312
313
|
document.removeEventListener("keypress", $), document.addEventListener("keypress", $);
|
|
313
314
|
}), ie(() => {
|
|
@@ -317,7 +318,7 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
317
318
|
u.value = o;
|
|
318
319
|
};
|
|
319
320
|
n.value = a.value;
|
|
320
|
-
const
|
|
321
|
+
const v = (o) => ({
|
|
321
322
|
[C.Top]: C.Right,
|
|
322
323
|
[C.Right]: C.Bottom,
|
|
323
324
|
[C.Bottom]: C.Left,
|
|
@@ -326,46 +327,46 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
326
327
|
if (e.value > -1) {
|
|
327
328
|
const o = n.value[e.value];
|
|
328
329
|
if (!o.sourcePosition) return;
|
|
329
|
-
o.sourcePosition =
|
|
330
|
+
o.sourcePosition = v(o.sourcePosition), N();
|
|
330
331
|
}
|
|
331
332
|
}, h = () => {
|
|
332
333
|
if (e.value > -1) {
|
|
333
334
|
const o = n.value[e.value];
|
|
334
335
|
if (!o.targetPosition) return;
|
|
335
|
-
o.targetPosition =
|
|
336
|
+
o.targetPosition = v(o.targetPosition), N();
|
|
336
337
|
}
|
|
337
338
|
}, k = (o) => {
|
|
338
339
|
window.scrollBy(0, o.deltaY);
|
|
339
340
|
}, $ = (o) => {
|
|
340
341
|
p.value && o.ctrlKey == !0 && ((o.key == "+" || o.key == "=") && u.value?.zoomIn(), o.key == "-" && u.value?.zoomOut());
|
|
341
|
-
},
|
|
342
|
+
}, L = async () => {
|
|
342
343
|
await u.value?.fitView();
|
|
343
344
|
}, j = async () => {
|
|
344
345
|
const o = u.value, i = {};
|
|
345
346
|
for (const b of n.value) {
|
|
346
347
|
if ("source" in b) continue;
|
|
347
|
-
const
|
|
348
|
-
|
|
348
|
+
const x = o?.findNode?.(b.id)?.dimensions;
|
|
349
|
+
x?.width && x?.height && (i[b.id] = { width: x.width, height: x.height });
|
|
349
350
|
}
|
|
350
|
-
const
|
|
351
|
-
for (const b of
|
|
351
|
+
const r = te(n.value, { dimensions: i }), w = /* @__PURE__ */ new Map();
|
|
352
|
+
for (const b of r)
|
|
352
353
|
"source" in b || w.set(b.id, b.position);
|
|
353
354
|
for (const b of n.value) {
|
|
354
355
|
if ("source" in b) continue;
|
|
355
|
-
const
|
|
356
|
-
|
|
356
|
+
const x = w.get(b.id);
|
|
357
|
+
x && (b.position = x);
|
|
357
358
|
}
|
|
358
|
-
N(), await
|
|
359
|
+
N(), await I(), await L();
|
|
359
360
|
}, z = () => {
|
|
360
361
|
let o = !1, i = { x: Math.random() * 200, y: Math.random() * 200 };
|
|
361
362
|
if (e.value > -1) {
|
|
362
363
|
const b = n.value[e.value];
|
|
363
364
|
b.data?.hasOutput && (i = { x: b.position.x + 200, y: b.position.y + 50 }, o = !0);
|
|
364
365
|
}
|
|
365
|
-
const
|
|
366
|
+
const r = n.value.length, w = `node-${r}`;
|
|
366
367
|
if (n.value.push({
|
|
367
368
|
id: w,
|
|
368
|
-
label: "Node " +
|
|
369
|
+
label: "Node " + r,
|
|
369
370
|
sourcePosition: C.Right,
|
|
370
371
|
targetPosition: C.Left,
|
|
371
372
|
class: "vue-flow__node-default",
|
|
@@ -376,21 +377,21 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
376
377
|
},
|
|
377
378
|
position: i
|
|
378
379
|
}), o) {
|
|
379
|
-
const b = `edge-${
|
|
380
|
+
const b = `edge-${r + 1}`;
|
|
380
381
|
n.value.push({
|
|
381
382
|
id: b,
|
|
382
383
|
source: t.value,
|
|
383
384
|
target: w,
|
|
384
385
|
type: "editable",
|
|
385
|
-
label: `EDGE ${
|
|
386
|
+
label: `EDGE ${r + 1}`,
|
|
386
387
|
animated: !0
|
|
387
388
|
});
|
|
388
389
|
}
|
|
389
390
|
N();
|
|
390
391
|
}, V = (o, i) => {
|
|
391
|
-
for (let
|
|
392
|
-
if (n.value[
|
|
393
|
-
n.value[
|
|
392
|
+
for (let r = 0; r < n.value.length; r++)
|
|
393
|
+
if (n.value[r].id == i) {
|
|
394
|
+
n.value[r].label = o;
|
|
394
395
|
break;
|
|
395
396
|
}
|
|
396
397
|
N();
|
|
@@ -399,35 +400,35 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
399
400
|
}, ae = ({ edge: o }) => {
|
|
400
401
|
t.value = o.id;
|
|
401
402
|
}, le = async (o) => {
|
|
402
|
-
const i = n.value.length,
|
|
403
|
+
const i = n.value.length, r = o.source === o.target, w = {
|
|
403
404
|
id: `edge-${i}`,
|
|
404
405
|
source: o.source,
|
|
405
406
|
target: o.target,
|
|
406
|
-
type:
|
|
407
|
+
type: r ? "selfloop" : "editable",
|
|
407
408
|
label: "New Edge",
|
|
408
409
|
interactionWidth: 400,
|
|
409
410
|
animated: !0
|
|
410
411
|
};
|
|
411
|
-
s([w]), await
|
|
412
|
+
s([w]), await I(), N();
|
|
412
413
|
}, se = async (o) => {
|
|
413
|
-
g([o.edge.id]), await
|
|
414
|
+
g([o.edge.id]), await I(), N();
|
|
414
415
|
}, G = async (o) => {
|
|
415
|
-
g([o]), await
|
|
416
|
+
g([o]), await I(), N();
|
|
416
417
|
}, N = () => {
|
|
417
|
-
|
|
418
|
+
d("update:modelValue", JSON.parse(JSON.stringify(n.value)));
|
|
418
419
|
};
|
|
419
420
|
return (o, i) => (S(), P("div", {
|
|
420
421
|
class: ue(["node-editor-wrapper", l.nodeContainerClass]),
|
|
421
422
|
onContextmenu: i[1] || (i[1] = D(() => {
|
|
422
423
|
}, ["prevent"])),
|
|
423
|
-
onMouseover: i[2] || (i[2] = (
|
|
424
|
-
onMouseleave: i[3] || (i[3] = (
|
|
424
|
+
onMouseover: i[2] || (i[2] = (r) => p.value = !0),
|
|
425
|
+
onMouseleave: i[3] || (i[3] = (r) => p.value = !1)
|
|
425
426
|
}, [
|
|
426
|
-
c("div",
|
|
427
|
-
c("div",
|
|
427
|
+
c("div", Ie, [
|
|
428
|
+
c("div", Le, [
|
|
428
429
|
c("div", null, [
|
|
429
430
|
i[4] || (i[4] = c("b", null, "Selected Node:", -1)),
|
|
430
|
-
|
|
431
|
+
re(" " + F(t.value ? t.value : "none"), 1)
|
|
431
432
|
])
|
|
432
433
|
]),
|
|
433
434
|
c("div", Oe, [
|
|
@@ -440,7 +441,7 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
440
441
|
c("div", null, [
|
|
441
442
|
c("button", {
|
|
442
443
|
class: "button-default",
|
|
443
|
-
onClick:
|
|
444
|
+
onClick: L
|
|
444
445
|
}, "Center")
|
|
445
446
|
]),
|
|
446
447
|
c("div", null, [
|
|
@@ -463,10 +464,10 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
463
464
|
])) : B("", !0)
|
|
464
465
|
])
|
|
465
466
|
]),
|
|
466
|
-
n.value && n.value.length ? (S(), H(_(
|
|
467
|
+
n.value && n.value.length ? (S(), H(_(ve), {
|
|
467
468
|
key: 0,
|
|
468
469
|
modelValue: n.value,
|
|
469
|
-
"onUpdate:modelValue": i[0] || (i[0] = (
|
|
470
|
+
"onUpdate:modelValue": i[0] || (i[0] = (r) => n.value = r),
|
|
470
471
|
class: "nowheel",
|
|
471
472
|
"prevent-scrolling": !0,
|
|
472
473
|
"zoom-on-scroll": !1,
|
|
@@ -480,21 +481,21 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
480
481
|
onNodeDragStop: N,
|
|
481
482
|
onWheel: D(k, ["prevent"])
|
|
482
483
|
}, {
|
|
483
|
-
"node-editable": R((
|
|
484
|
-
O($e, A(
|
|
485
|
-
onChange: (w) => V(w,
|
|
484
|
+
"node-editable": R((r) => [
|
|
485
|
+
O($e, A(r, {
|
|
486
|
+
onChange: (w) => V(w, r.id)
|
|
486
487
|
}), null, 16, ["onChange"])
|
|
487
488
|
]),
|
|
488
|
-
"edge-editable": R((
|
|
489
|
-
O(ke, A(
|
|
490
|
-
onChange: (w) => V(w,
|
|
491
|
-
onRemove: (w) => G(
|
|
489
|
+
"edge-editable": R((r) => [
|
|
490
|
+
O(ke, A(r, {
|
|
491
|
+
onChange: (w) => V(w, r.id),
|
|
492
|
+
onRemove: (w) => G(r.id)
|
|
492
493
|
}), null, 16, ["onChange", "onRemove"])
|
|
493
494
|
]),
|
|
494
|
-
"edge-selfloop": R((
|
|
495
|
-
O(
|
|
496
|
-
onChange: (w) => V(w,
|
|
497
|
-
onRemove: (w) => G(
|
|
495
|
+
"edge-selfloop": R((r) => [
|
|
496
|
+
O(xe, A(r, {
|
|
497
|
+
onChange: (w) => V(w, r.id),
|
|
498
|
+
onRemove: (w) => G(r.id)
|
|
498
499
|
}), null, 16, ["onChange", "onRemove"])
|
|
499
500
|
]),
|
|
500
501
|
_: 1
|
|
@@ -502,8 +503,8 @@ const Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, O
|
|
|
502
503
|
], 34));
|
|
503
504
|
}
|
|
504
505
|
});
|
|
505
|
-
function Me(l,
|
|
506
|
-
const { states:
|
|
506
|
+
function Me(l, f) {
|
|
507
|
+
const { states: d = [], actions: p = {} } = l, n = [], u = [];
|
|
507
508
|
for (const [t, e] of Object.entries(p))
|
|
508
509
|
if (!(e.stateless || !e.allowedStates?.length)) {
|
|
509
510
|
if (e.selfTransition) {
|
|
@@ -535,24 +536,24 @@ function Me(l, v) {
|
|
|
535
536
|
interactionWidth: 40
|
|
536
537
|
});
|
|
537
538
|
}
|
|
538
|
-
for (let t = 0; t <
|
|
539
|
-
const e =
|
|
539
|
+
for (let t = 0; t < d.length; t++) {
|
|
540
|
+
const e = d[t], a = {
|
|
540
541
|
id: e,
|
|
541
542
|
label: e,
|
|
542
|
-
position:
|
|
543
|
-
targetPosition:
|
|
544
|
-
sourcePosition:
|
|
543
|
+
position: f?.[e]?.position ?? { x: 200 * t, y: 100 },
|
|
544
|
+
targetPosition: f?.[e]?.targetPosition ?? C.Left,
|
|
545
|
+
sourcePosition: f?.[e]?.sourcePosition ?? C.Right
|
|
545
546
|
};
|
|
546
547
|
u.push(a);
|
|
547
548
|
}
|
|
548
549
|
return [...n, ...u];
|
|
549
550
|
}
|
|
550
|
-
function _e(l,
|
|
551
|
-
const
|
|
551
|
+
function _e(l, f) {
|
|
552
|
+
const d = {}, p = {}, n = [];
|
|
552
553
|
for (const e of l) {
|
|
553
554
|
if ("source" in e) continue;
|
|
554
555
|
const a = typeof e.label == "string" ? e.label : e.id;
|
|
555
|
-
|
|
556
|
+
d[e.id] = a, n.push(a), e.position && (p[a] = {
|
|
556
557
|
position: e.position,
|
|
557
558
|
...e.targetPosition !== void 0 && { targetPosition: e.targetPosition },
|
|
558
559
|
...e.sourcePosition !== void 0 && { sourcePosition: e.sourcePosition }
|
|
@@ -561,17 +562,17 @@ function _e(l, v) {
|
|
|
561
562
|
const u = {};
|
|
562
563
|
for (const e of l) {
|
|
563
564
|
if (!("source" in e)) continue;
|
|
564
|
-
const a = typeof e.label == "string" ? e.label : e.id, s = e.data?.actionKey ?? a, g =
|
|
565
|
+
const a = typeof e.label == "string" ? e.label : e.id, s = e.data?.actionKey ?? a, g = d[e.source] || e.source, m = d[e.target] || e.target, v = e.source === e.target;
|
|
565
566
|
u[s] ? u[s].allowedStates.push(g) : u[s] = {
|
|
566
567
|
allowedStates: [g],
|
|
567
568
|
label: a,
|
|
568
|
-
selfLoop:
|
|
569
|
-
...
|
|
569
|
+
selfLoop: v,
|
|
570
|
+
...v ? {} : { nextState: m }
|
|
570
571
|
};
|
|
571
572
|
}
|
|
572
573
|
const t = {};
|
|
573
574
|
for (const [e, a] of Object.entries(u)) {
|
|
574
|
-
const s =
|
|
575
|
+
const s = f?.actions?.[e];
|
|
575
576
|
t[e] = {
|
|
576
577
|
// Spread existing first so every field the graph does NOT own — clientHandler,
|
|
577
578
|
// requiredFields and any field added to ActionDefinition later — survives the
|
|
@@ -590,7 +591,7 @@ function _e(l, v) {
|
|
|
590
591
|
selfTransition: a.selfLoop ? !0 : void 0
|
|
591
592
|
};
|
|
592
593
|
}
|
|
593
|
-
for (const [e, a] of Object.entries(
|
|
594
|
+
for (const [e, a] of Object.entries(f?.actions ?? {}))
|
|
594
595
|
e in u || (a.stateless || !a.allowedStates?.length) && (t[e] = a);
|
|
595
596
|
return {
|
|
596
597
|
// Spread existingWorkflow first so every top-level key the graph does NOT own — the
|
|
@@ -598,13 +599,13 @@ function _e(l, v) {
|
|
|
598
599
|
// later — survives the round-trip. The graph owns topology only: states + actions,
|
|
599
600
|
// overridden below. (Same principle the per-action spread applies above; enumerating
|
|
600
601
|
// only states+actions here previously dropped `triggers` on every graph edit.)
|
|
601
|
-
workflow: { ...
|
|
602
|
+
workflow: { ...f, states: n, actions: t },
|
|
602
603
|
layout: p
|
|
603
604
|
};
|
|
604
605
|
}
|
|
605
606
|
const Te = /* @__PURE__ */ T({
|
|
606
607
|
__name: "StateEditor",
|
|
607
|
-
props: /* @__PURE__ */
|
|
608
|
+
props: /* @__PURE__ */ de({
|
|
608
609
|
nodeContainerClass: { type: [Boolean, null, String, Object, Array], default: "" }
|
|
609
610
|
}, {
|
|
610
611
|
modelValue: {},
|
|
@@ -614,19 +615,19 @@ const Te = /* @__PURE__ */ T({
|
|
|
614
615
|
}),
|
|
615
616
|
emits: ["update:modelValue", "update:layout"],
|
|
616
617
|
setup(l) {
|
|
617
|
-
const
|
|
618
|
+
const f = J(l, "modelValue"), d = J(l, "layout");
|
|
618
619
|
Z(() => {
|
|
619
|
-
|
|
620
|
+
d.value === void 0 && console.warn("[StateEditor] v-model:layout is not bound. Node position changes will not be persisted.");
|
|
620
621
|
});
|
|
621
622
|
const p = M({
|
|
622
623
|
get: () => {
|
|
623
|
-
if (!
|
|
624
|
-
const n = Me(
|
|
625
|
-
return !
|
|
624
|
+
if (!f.value) return [];
|
|
625
|
+
const n = Me(f.value, d.value);
|
|
626
|
+
return !d.value || Object.keys(d.value).length === 0 ? te(n) : n;
|
|
626
627
|
},
|
|
627
628
|
set: (n) => {
|
|
628
|
-
const { workflow: u, layout: t } = _e(n,
|
|
629
|
-
|
|
629
|
+
const { workflow: u, layout: t } = _e(n, f.value);
|
|
630
|
+
f.value = u, d.value !== void 0 && (d.value = t);
|
|
630
631
|
}
|
|
631
632
|
});
|
|
632
633
|
return (n, u) => (S(), P("div", null, [
|
|
@@ -643,6 +644,7 @@ function je(l) {
|
|
|
643
644
|
}
|
|
644
645
|
export {
|
|
645
646
|
oe as NodeEditor,
|
|
647
|
+
He as Position,
|
|
646
648
|
Te as StateEditor,
|
|
647
649
|
je as install
|
|
648
650
|
};
|
package/dist/node-editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-editor.js","sources":["../src/components/EditableEdge.vue","../src/components/EditableNode.vue","../src/components/SelfLoopEdge.vue","../src/utils/autoLayout.ts","../src/components/NodeEditor.vue","../src/utils/stateTransforms.ts","../src/components/StateEditor.vue","../src/index.ts"],"sourcesContent":["<template>\n\t<!-- transparent ghost path gives a ~20px click zone around the 2px visible stroke -->\n\t<path :d=\"path[0]\" fill=\"none\" stroke=\"transparent\" stroke-width=\"20\" class=\"vue-flow__edge-interaction\" />\n\t<path :id=\"id\" :style=\"style\" class=\"vue-flow__edge-path\" :d=\"path[0]\" :marker-end=\"markerEnd\" />\n\n\t<EdgeLabelRenderer>\n\t\t<div\n\t\t\t:style=\"{\n\t\t\t\tpointerEvents: 'all',\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttransform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,\n\t\t\t}\"\n\t\t\tclass=\"nodrag nopan editable-edge-label\"\n\t\t\t@click=\"labelOnClick()\"\n\t\t\t@contextmenu.prevent=\"$emit('remove', id)\">\n\t\t\t<div class=\"vue-flow__edge-label\">{{ label }}</div>\n\t\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t\t<input\n\t\t\t\t\tref=\"labelInput\"\n\t\t\t\t\tv-model=\"newLabel\"\n\t\t\t\t\tclass=\"label-input\"\n\t\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t\t</div>\n\t\t</div>\n\t</EdgeLabelRenderer>\n</template>\n\n<script setup lang=\"ts\">\nimport { type EdgeProps, EdgeLabelRenderer, getBezierPath /* useVueFlow */ } from '@vue-flow/core'\nimport { computed, ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<EdgeProps>()\nconst emit = defineEmits(['change', 'remove'])\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<EdgeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst labelOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n\nconst path = computed(() => getBezierPath(props))\n</script>\n\n<script lang=\"ts\">\nexport default {\n\tinheritAttrs: false,\n}\n</script>\n\n<style>\n.editable-edge-label {\n\tbackground-color: white;\n\tposition: relative;\n\tfont-size: 12px;\n}\n\n.label-input-wrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.label-input {\n\ttext-align: center;\n\twidth: 40ch;\n}\n</style>\n","<template>\n\t<div @click=\"nodeOnClick()\">\n\t\t<div>{{ label }}</div>\n\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t<input\n\t\t\t\tref=\"labelInput\"\n\t\t\t\tv-model=\"newLabel\"\n\t\t\t\tclass=\"label-input\"\n\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t</div>\n\t\t<Handle v-if=\"data.hasInput\" id=\"a\" type=\"target\" :position=\"targetPosition\" />\n\t\t<Handle v-if=\"data.hasOutput\" id=\"b\" type=\"source\" :position=\"sourcePosition\" />\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { NodeProps, Handle } from '@vue-flow/core'\nimport { ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<NodeProps>()\nconst emit = defineEmits(['change'])\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<NodeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst nodeOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n</script>\n\n<style>\n.label-input-wrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.label-input {\n\ttext-align: center;\n}\n</style>\n","<template>\n\t<!-- transparent ghost path gives a ~20px click zone around the 2px visible stroke -->\n\t<path :d=\"path.d\" fill=\"none\" stroke=\"transparent\" stroke-width=\"20\" class=\"vue-flow__edge-interaction\" />\n\t<path :id=\"id\" :style=\"style\" class=\"vue-flow__edge-path\" :d=\"path.d\" :marker-end=\"markerEnd\" />\n\n\t<EdgeLabelRenderer>\n\t\t<div\n\t\t\t:style=\"{\n\t\t\t\tpointerEvents: 'all',\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttransform: `translate(-50%, -50%) translate(${path.labelX}px,${path.labelY}px)`,\n\t\t\t}\"\n\t\t\tclass=\"nodrag nopan editable-edge-label\"\n\t\t\t@click=\"labelOnClick()\"\n\t\t\t@contextmenu.prevent=\"$emit('remove', id)\">\n\t\t\t<div class=\"vue-flow__edge-label\">{{ label }}</div>\n\t\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t\t<input\n\t\t\t\t\tref=\"labelInput\"\n\t\t\t\t\tv-model=\"newLabel\"\n\t\t\t\t\tclass=\"label-input\"\n\t\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t\t</div>\n\t\t</div>\n\t</EdgeLabelRenderer>\n</template>\n\n<script setup lang=\"ts\">\nimport { type EdgeProps, EdgeLabelRenderer } from '@vue-flow/core'\nimport { computed, ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<EdgeProps>()\nconst emit = defineEmits(['change', 'remove'])\n\n// A self-loop connects a node's source handle to its own target handle. getBezierPath draws a nearly\n// straight segment across the node for that (the two handles are on the same box), so it's useless\n// here — we hand-author an arc that leaves the source handle, loops up and over the node top, and\n// returns to the target handle. LOOP_HEIGHT is how far above the handles the arc bulges.\nconst LOOP_HEIGHT = 90\nconst LOOP_SPREAD = 45\n\nconst path = computed(() => {\n\tconst { sourceX, sourceY, targetX, targetY } = props\n\tconst d = `M ${sourceX},${sourceY} C ${sourceX + LOOP_SPREAD},${sourceY - LOOP_HEIGHT} ${\n\t\ttargetX - LOOP_SPREAD\n\t},${targetY - LOOP_HEIGHT} ${targetX},${targetY}`\n\t// Place the label near the arc's apex (a cubic bezier peaks around 0.75 of the control offset).\n\tconst labelX = (sourceX + targetX) / 2\n\tconst labelY = Math.min(sourceY, targetY) - LOOP_HEIGHT * 0.72\n\treturn { d, labelX, labelY }\n})\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<EdgeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst labelOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n</script>\n\n<script lang=\"ts\">\nexport default {\n\tinheritAttrs: false,\n}\n</script>\n\n<style>\n/* Label + input styles are shared with EditableEdge (defined there, global scope). */\n</style>\n","import { Graph, layout } from '@dagrejs/dagre'\n\nimport type { FlowElements } from '../types'\n\n/**\n * Options for {@link autoLayout}.\n * @public\n */\nexport interface AutoLayoutOptions {\n\t/** Layout direction. Defaults to `'LR'` to match the editor's Left/Right handle defaults. */\n\trankdir?: 'LR' | 'RL' | 'TB' | 'BT'\n\t/** Fallback node width when no measured size is supplied (the seed path has no DOM to measure). */\n\tnodeWidth?: number\n\t/** Fallback node height when no measured size is supplied. */\n\tnodeHeight?: number\n\t/** Measured per-node sizes (node id → box) — supplied by the on-demand \"Auto-arrange\" button. */\n\tdimensions?: Record<string, { width: number; height: number }>\n}\n\n/**\n * Compute node positions for a workflow graph with dagre's layered (Sugiyama) algorithm.\n *\n * Pure and synchronous: takes VueFlow elements (nodes + edges) and returns a new elements array with\n * each node's `position` replaced by a laid-out coordinate; edges and every other node field are\n * passed through untouched. Used two ways — as the seed for an un-arranged workflow (fixed default\n * dimensions, no DOM) and behind the toolbar button (measured `dimensions`).\n *\n * Self-loop edges (`source === target`) are skipped: dagre doesn't rank them, and they're reserved\n * for the separate mutate-in-place self-transition feature.\n * @public\n */\nexport function autoLayout(elements: FlowElements, options: AutoLayoutOptions = {}): FlowElements {\n\tconst { rankdir = 'LR', nodeWidth = 160, nodeHeight = 40, dimensions } = options\n\tconst sizeOf = (id: string) => dimensions?.[id] ?? { width: nodeWidth, height: nodeHeight }\n\n\t// Nodes are the elements without a `source` (the same discriminator flowElementsToStates uses).\n\tconst nodeIds: string[] = []\n\tfor (const el of elements) {\n\t\tif (!('source' in el)) nodeIds.push(el.id)\n\t}\n\tif (nodeIds.length === 0) return [...elements]\n\n\tconst graph = new Graph()\n\tgraph.setGraph({ rankdir, nodesep: 40, ranksep: 80, edgesep: 20 })\n\tgraph.setDefaultEdgeLabel(() => ({}))\n\n\tfor (const id of nodeIds) {\n\t\tconst { width, height } = sizeOf(id)\n\t\tgraph.setNode(id, { width, height })\n\t}\n\tfor (const el of elements) {\n\t\tif (!('source' in el)) continue\n\t\tif (el.source === el.target) continue\n\t\tgraph.setEdge(el.source, el.target)\n\t}\n\n\tlayout(graph)\n\n\t// dagre reports each node by its CENTER; VueFlow positions nodes by their TOP-LEFT corner.\n\treturn elements.map(el => {\n\t\tif ('source' in el) return el\n\t\tconst center = graph.node(el.id)\n\t\tif (!center) return el\n\t\tconst { width, height } = sizeOf(el.id)\n\t\treturn { ...el, position: { x: center.x - width / 2, y: center.y - height / 2 } }\n\t})\n}\n","<template>\n\t<div\n\t\tclass=\"node-editor-wrapper\"\n\t\t:class=\"nodeContainerClass\"\n\t\t@contextmenu.prevent\n\t\t@mouseover=\"hover = true\"\n\t\t@mouseleave=\"hover = false\">\n\t\t<div class=\"chart-controls\">\n\t\t\t<div class=\"chart-controls-left\">\n\t\t\t\t<div><b>Selected Node:</b> {{ activeElementKey ? activeElementKey : 'none' }}</div>\n\t\t\t</div>\n\t\t\t<div class=\"chart-controls-right\">\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"addNode\">Add Node</button>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"fitView\">Center</button>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"autoArrange\">Auto-arrange</button>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"activeElementIndex > -1\">\n\t\t\t\t\t<button class=\"button-default\" @click=\"shiftInput\">Shift Input Position</button>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"activeElementIndex > -1\">\n\t\t\t\t\t<button class=\"button-default\" @click=\"shiftOutput\">Shift Output Position</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<VueFlow\n\t\t\tv-if=\"vueFlowElements && vueFlowElements.length\"\n\t\t\tv-model=\"vueFlowElements\"\n\t\t\tclass=\"nowheel\"\n\t\t\t:prevent-scrolling=\"true\"\n\t\t\t:zoom-on-scroll=\"false\"\n\t\t\t:fit-view-on-init=\"true\"\n\t\t\t:pan-activation-key-code=\"null\"\n\t\t\t@connect=\"handleConnect\"\n\t\t\t@pane-ready=\"setInstance\"\n\t\t\t@node-click=\"handleNodeClick\"\n\t\t\t@edge-click=\"handleEdgeClick\"\n\t\t\t@edge-context-menu=\"handleEdgeContextMenu\"\n\t\t\t@node-drag-stop=\"emitElements\"\n\t\t\t@wheel.prevent=\"onWheel\">\n\t\t\t<template #node-editable=\"props\">\n\t\t\t\t<EditableNode v-bind=\"props\" @change=\"labelChanged($event, props.id)\" />\n\t\t\t</template>\n\t\t\t<template #edge-editable=\"props\">\n\t\t\t\t<EditableEdge v-bind=\"props\" @change=\"labelChanged($event, props.id)\" @remove=\"removeEdge(props.id)\" />\n\t\t\t</template>\n\t\t\t<template #edge-selfloop=\"props\">\n\t\t\t\t<SelfLoopEdge v-bind=\"props\" @change=\"labelChanged($event, props.id)\" @remove=\"removeEdge(props.id)\" />\n\t\t\t</template>\n\t\t</VueFlow>\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n\ttype VueFlowStore,\n\tPosition,\n\tVueFlow,\n\tuseVueFlow,\n\tConnection,\n\tNode,\n\tNodeMouseEvent,\n\tEdgeMouseEvent,\n\tDefaultEdge,\n} from '@vue-flow/core'\nimport { type HTMLAttributes, ref, computed, nextTick, onBeforeUnmount, onMounted } from 'vue'\n\nimport EditableEdge from './EditableEdge.vue'\nimport EditableNode from './EditableNode.vue'\nimport SelfLoopEdge from './SelfLoopEdge.vue'\nimport { autoLayout } from '../utils/autoLayout'\nimport type { FlowElements } from '../types'\n\nconst { modelValue, nodeContainerClass = '' } = defineProps<{\n\tmodelValue: FlowElements\n\tnodeContainerClass?: HTMLAttributes['class']\n}>()\nconst emit = defineEmits(['update:modelValue'])\n\nconst hover = ref(false)\nconst vueFlowElements = ref<FlowElements>([])\nconst vueFlowInstance = ref<VueFlowStore>()\n\nconst activeElementKey = ref('')\nconst activeElementIndex = computed(() =>\n\tvueFlowElements.value.findIndex(element => element.id === activeElementKey.value)\n)\n\nconst elements = computed({\n\tget: () => {\n\t\tconst items = modelValue\n\n\t\t// Add rendering flags without clobbering caller-provided data. Edges carry `data.actionKey`\n\t\t// (the stable action identity from stateTransforms); wiping data here would drop it before it\n\t\t// round-trips back through emitElements, silently re-keying actions on every graph edit.\n\t\tfor (const element of items) {\n\t\t\telement.data = { ...element.data }\n\t\t\tif (element.type === 'input') {\n\t\t\t\telement.data.hasInput = false\n\t\t\t\telement.data.hasOutput = true\n\t\t\t} else if (element.type === 'output') {\n\t\t\t\telement.data.hasInput = true\n\t\t\t\telement.data.hasOutput = false\n\t\t\t} else {\n\t\t\t\telement.data.hasInput = true\n\t\t\t\telement.data.hasOutput = true\n\t\t\t}\n\t\t\telement.class = 'vue-flow__node-default'\n\t\t\t// A self-loop edge (source === target) routes to the SelfLoopEdge arc renderer; everything\n\t\t\t// else (nodes and cross-state edges) uses the default editable slot. getBezierPath draws a\n\t\t\t// useless near-straight segment for a self-loop, so it must not fall through to 'editable'.\n\t\t\telement.type = 'source' in element && element.source === element.target ? 'selfloop' : 'editable'\n\t\t}\n\n\t\treturn items\n\t},\n\tset: newValue => {\n\t\temit('update:modelValue', JSON.parse(JSON.stringify(newValue)))\n\t},\n})\nconst { addEdges, removeEdges } = useVueFlow()\n\nonMounted(() => {\n\tdocument.removeEventListener('keypress', handleKeypress)\n\tdocument.addEventListener('keypress', handleKeypress)\n})\n\nonBeforeUnmount(() => {\n\tdocument.removeEventListener('keypress', handleKeypress)\n})\n\nconst setInstance = (instance: VueFlowStore) => {\n\tvueFlowInstance.value = instance\n}\n\nvueFlowElements.value = elements.value\n\n// Methods\nconst shiftTerminal = (currentTerminal: Position) => {\n\treturn {\n\t\t[Position.Top]: Position.Right,\n\t\t[Position.Right]: Position.Bottom,\n\t\t[Position.Bottom]: Position.Left,\n\t\t[Position.Left]: Position.Top,\n\t}[currentTerminal]\n}\n\nconst shiftOutput = () => {\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value] as Node\n\t\tif (!activeNode.sourcePosition) return\n\t\tactiveNode.sourcePosition = shiftTerminal(activeNode.sourcePosition)\n\t\temitElements()\n\t}\n}\n\nconst shiftInput = () => {\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value] as Node\n\t\tif (!activeNode.targetPosition) return\n\t\tactiveNode.targetPosition = shiftTerminal(activeNode.targetPosition)\n\t\temitElements()\n\t}\n}\n\nconst onWheel = (event: WheelEvent) => {\n\twindow.scrollBy(0, event.deltaY)\n}\n\nconst handleKeypress = (event: KeyboardEvent) => {\n\tif (hover.value && event.ctrlKey == true) {\n\t\tif (event.key == '+' || event.key == '=') {\n\t\t\tvoid vueFlowInstance.value?.zoomIn()\n\t\t}\n\t\tif (event.key == '-') {\n\t\t\tvoid vueFlowInstance.value?.zoomOut()\n\t\t}\n\t}\n}\n\nconst fitView = async () => {\n\tawait vueFlowInstance.value?.fitView()\n}\n\nconst autoArrange = async () => {\n\t// Read measured node sizes from the VueFlow store so the layout fits actual box widths (state\n\t// labels differ in length); autoLayout falls back to default dimensions for any unmeasured node.\n\tconst store = vueFlowInstance.value\n\tconst dimensions: Record<string, { width: number; height: number }> = {}\n\tfor (const el of vueFlowElements.value) {\n\t\tif ('source' in el) continue\n\t\tconst dims = store?.findNode?.(el.id)?.dimensions\n\t\tif (dims?.width && dims?.height) dimensions[el.id] = { width: dims.width, height: dims.height }\n\t}\n\n\tconst laid = autoLayout(vueFlowElements.value, { dimensions })\n\tconst positionById = new Map<string, { x: number; y: number }>()\n\tfor (const el of laid) {\n\t\tif ('source' in el) continue\n\t\tpositionById.set(el.id, el.position)\n\t}\n\t// Apply positions onto the v-model elements — VueFlow reacts to these, same as shiftInput/Output.\n\tfor (const el of vueFlowElements.value) {\n\t\tif ('source' in el) continue\n\t\tconst position = positionById.get(el.id)\n\t\tif (position) el.position = position\n\t}\n\n\temitElements()\n\tawait nextTick()\n\tawait fitView()\n}\n\nconst addNode = () => {\n\tlet makeEdge = false\n\tlet newNodePosition = { x: Math.random() * 200, y: Math.random() * 200 }\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value]\n\t\tif (activeNode.data?.hasOutput) {\n\t\t\tnewNodePosition = { x: (activeNode as Node).position.x + 200, y: (activeNode as Node).position.y + 50 }\n\t\t\tmakeEdge = true\n\t\t}\n\t}\n\n\tconst id = vueFlowElements.value.length\n\tconst nodeId = `node-${id}`\n\tvueFlowElements.value.push({\n\t\tid: nodeId,\n\t\tlabel: 'Node ' + id,\n\t\tsourcePosition: Position.Right,\n\t\ttargetPosition: Position.Left,\n\t\tclass: 'vue-flow__node-default',\n\t\ttype: 'editable',\n\t\tdata: {\n\t\t\thasInput: true,\n\t\t\thasOutput: true,\n\t\t},\n\t\tposition: newNodePosition,\n\t})\n\n\tif (makeEdge) {\n\t\tconst edgeId = `edge-${id + 1}`\n\t\tvueFlowElements.value.push({\n\t\t\tid: edgeId,\n\t\t\tsource: activeElementKey.value,\n\t\t\ttarget: nodeId,\n\t\t\ttype: 'editable',\n\t\t\tlabel: `EDGE ${id + 1}`,\n\t\t\tanimated: true,\n\t\t})\n\t}\n\temitElements()\n}\n\nconst labelChanged = (event: DefaultEdge['label'], id: DefaultEdge['id']) => {\n\tfor (let j = 0; j < vueFlowElements.value.length; j++) {\n\t\tif (vueFlowElements.value[j].id == id) {\n\t\t\tvueFlowElements.value[j].label = event\n\t\t\tbreak\n\t\t}\n\t}\n\temitElements()\n}\n\nconst handleNodeClick = ({ node }: NodeMouseEvent) => {\n\tactiveElementKey.value = node.id\n}\n\nconst handleEdgeClick = ({ edge }: EdgeMouseEvent) => {\n\tactiveElementKey.value = edge.id\n}\n\nconst handleConnect = async (event: Connection) => {\n\tconst id = vueFlowElements.value.length\n\t// A node connected to itself is a self-transition (mutate-in-place) — render it as a loop.\n\tconst isSelfLoop = event.source === event.target\n\tconst newEdge = {\n\t\tid: `edge-${id}`,\n\t\tsource: event.source,\n\t\ttarget: event.target,\n\t\ttype: isSelfLoop ? 'selfloop' : 'editable',\n\t\tlabel: `New Edge`,\n\t\tinteractionWidth: 400,\n\t\tanimated: true,\n\t}\n\taddEdges([newEdge])\n\tawait nextTick()\n\temitElements()\n}\n\nconst handleEdgeContextMenu = async (event: EdgeMouseEvent) => {\n\tremoveEdges([event.edge.id])\n\tawait nextTick()\n\temitElements()\n}\n\nconst removeEdge = async (id: string) => {\n\tremoveEdges([id])\n\tawait nextTick()\n\temitElements()\n}\n\nconst emitElements = () => {\n\temit('update:modelValue', JSON.parse(JSON.stringify(vueFlowElements.value)))\n}\n</script>\n\n<style>\n@import '@vue-flow/core/dist/style.css';\n@import '@vue-flow/core/dist/theme-default.css';\n\n.chart-controls-left,\n.chart-controls-right {\n\theight: 1.8em;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tpadding-top: 0.2em;\n}\n\n.chart-controls-right div {\n\tmargin-left: 5px;\n}\n\n.chart-controls {\n\tposition: absolute;\n\tbottom: 0.5rem;\n\tleft: 0.5rem;\n\tz-index: 10;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\tgap: 0.35rem;\n\tpadding: 0.4rem 0.5rem;\n\tbackground: rgba(255, 255, 255, 0.92);\n\tborder: 1px solid #ccc;\n\tborder-radius: 4px;\n\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.chart-controls div {\n\tmargin-bottom: 0;\n}\n\n.defaultContainerClass {\n\theight: 90vh;\n\twidth: 100%;\n\tborder: 1px solid #ccc;\n}\n\n.default-input-node.vue-flow__node-input,\n.default-output-node.vue-flow__node-output {\n\tborder-color: #000;\n}\n\n.default-input-node.vue-flow__node-input .vue-flow__handle,\n.default-output-node.vue-flow__node-output .vue-flow__handle {\n\tbackground-color: #000;\n}\n\n.default-input-node.vue-flow__node-input.selected,\n.default-output-node.vue-flow__node-output.selected {\n\tbox-shadow: 0 0 0 0.5px #000;\n}\n\nbutton.button-default {\n\tbackground-color: #ffffff;\n\tpadding: 1px 12px;\n\tborder-radius: 3px;\n\tborder: 1px solid #ccc;\n\tcursor: pointer;\n\twhite-space: nowrap;\n}\n\nbutton.button-default:hover {\n\tbackground-color: #f2f2f2;\n}\n\n.vue-flow {\n\tbackground-size: 40px 40px;\n\tbackground-image:\n\t\tlinear-gradient(to right, #ccc 1px, transparent 1px), linear-gradient(to bottom, #ccc 1px, transparent 1px);\n}\n\ninput.label-editor {\n\tposition: absolute;\n}\n\n.node-editor-wrapper {\n\tposition: relative;\n}\n</style>\n","import { Position, type Node } from '@vue-flow/core'\nimport type { ActionDefinition, WorkflowMeta } from '@stonecrop/schema'\n\nimport type { FlowElements, Layout } from '../types'\n\nexport function statesToFlowElements(workflow: WorkflowMeta, layout?: Layout): FlowElements {\n\tconst { states = [], actions = {} } = workflow\n\tconst edges: FlowElements = []\n\tconst nodes: Node[] = []\n\n\tfor (const [actionKey, actionDef] of Object.entries(actions)) {\n\t\t// Stateless commands (print/email) have no graph presence; anything graph-owned needs states.\n\t\tif (actionDef.stateless || !actionDef.allowedStates?.length) continue\n\n\t\t// A self-transition (mutate-in-place `save`) renders as a self-loop on each allowed state:\n\t\t// `source === target`, tagged `selfloop` so NodeEditor routes it to the arc renderer.\n\t\tif (actionDef.selfTransition) {\n\t\t\tfor (const source of actionDef.allowedStates) {\n\t\t\t\tedges.push({\n\t\t\t\t\tid: `${actionKey}-${source}`,\n\t\t\t\t\tsource,\n\t\t\t\t\ttarget: source,\n\t\t\t\t\tlabel: actionDef.label ?? actionKey,\n\t\t\t\t\tdata: { actionKey },\n\t\t\t\t\tanimated: true,\n\t\t\t\t\ttype: 'selfloop',\n\t\t\t\t\tinteractionWidth: 40,\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// A cross-state transition needs a target; a malformed action with neither is skipped.\n\t\tif (!actionDef.nextState) continue\n\t\tfor (const source of actionDef.allowedStates) {\n\t\t\tedges.push({\n\t\t\t\tid: `${actionKey}-${source}`,\n\t\t\t\tsource,\n\t\t\t\ttarget: actionDef.nextState,\n\t\t\t\t// The edge paints the human display label; its identity (the action key) rides in\n\t\t\t\t// `data.actionKey`, so relabeling the edge renames the action without re-keying it.\n\t\t\t\tlabel: actionDef.label ?? actionKey,\n\t\t\t\tdata: { actionKey },\n\t\t\t\tanimated: true,\n\t\t\t\ttype: 'smoothstep',\n\t\t\t\tinteractionWidth: 40,\n\t\t\t})\n\t\t}\n\t}\n\n\tfor (let index = 0; index < states.length; index++) {\n\t\tconst state = states[index]\n\t\tconst node: Node = {\n\t\t\tid: state,\n\t\t\tlabel: state,\n\t\t\tposition: layout?.[state]?.position ?? { x: 200 * index, y: 100 },\n\t\t\ttargetPosition: layout?.[state]?.targetPosition ?? Position.Left,\n\t\t\tsourcePosition: layout?.[state]?.sourcePosition ?? Position.Right,\n\t\t}\n\t\t// Every state renders identically — both handles, no start-state styling — so any transition\n\t\t// (including a returning `reject`/`reopen` into the initial state) is authorable and a\n\t\t// self-loop can anchor both ends. Marking an entry state is deferred (YAGNI) until needed.\n\t\tnodes.push(node)\n\t}\n\n\treturn [...edges, ...nodes]\n}\n\nexport function flowElementsToStates(\n\tnextElements: FlowElements,\n\texistingWorkflow?: WorkflowMeta\n): { workflow: WorkflowMeta; layout: Layout } {\n\tconst idToLabel: Record<string, string> = {}\n\tconst nextLayout: Layout = {}\n\tconst stateNames: string[] = []\n\n\tfor (const el of nextElements) {\n\t\tif ('source' in el) continue\n\t\tconst label = typeof el.label === 'string' ? el.label : el.id\n\t\tidToLabel[el.id] = label\n\t\tstateNames.push(label)\n\t\tif (el.position) {\n\t\t\tnextLayout[label] = {\n\t\t\t\tposition: el.position,\n\t\t\t\t...(el.targetPosition !== undefined && { targetPosition: el.targetPosition }),\n\t\t\t\t...(el.sourcePosition !== undefined && { sourcePosition: el.sourcePosition }),\n\t\t\t}\n\t\t}\n\t}\n\n\t// Group directed edges by their stable action key. A round-tripped edge carries the key in\n\t// `data.actionKey`; a freshly-drawn edge (no data yet) falls back to its label as the key — the\n\t// one moment label and key coincide, when the action is first born. The edge's label is captured\n\t// separately as the display name, so a later relabel renames the action without re-keying it.\n\tconst transitionGroups: Record<\n\t\tstring,\n\t\t{ nextState?: string; allowedStates: string[]; label: string; selfLoop: boolean }\n\t> = {}\n\tfor (const el of nextElements) {\n\t\tif (!('source' in el)) continue\n\t\tconst edgeLabel = typeof el.label === 'string' ? el.label : el.id\n\t\tconst actionKey = el.data?.actionKey ?? edgeLabel\n\t\tconst sourceLabel = idToLabel[el.source] || el.source\n\t\tconst targetLabel = idToLabel[el.target] || el.target\n\t\t// Classify by topology, not by edge `type`: a self-loop (source === target) round-trips to a\n\t\t// self-transition regardless of how it was authored (drawn node→itself, or re-rendered from a\n\t\t// `selfTransition` action). A group's kind is set by its first edge; a multi-state self-loop\n\t\t// (e.g. `save` on Draft AND Pending) accumulates each source into allowedStates.\n\t\tconst isSelf = el.source === el.target\n\t\tif (!transitionGroups[actionKey]) {\n\t\t\ttransitionGroups[actionKey] = {\n\t\t\t\tallowedStates: [sourceLabel],\n\t\t\t\tlabel: edgeLabel,\n\t\t\t\tselfLoop: isSelf,\n\t\t\t\t...(isSelf ? {} : { nextState: targetLabel }),\n\t\t\t}\n\t\t} else {\n\t\t\ttransitionGroups[actionKey].allowedStates.push(sourceLabel)\n\t\t}\n\t}\n\n\tconst nextActions: Record<string, ActionDefinition> = {}\n\n\t// Transitions (and self-transitions) derived from graph edges\n\tfor (const [actionKey, group] of Object.entries(transitionGroups)) {\n\t\tconst existing = existingWorkflow?.actions?.[actionKey]\n\t\tnextActions[actionKey] = {\n\t\t\t// Spread existing first so every field the graph does NOT own — clientHandler,\n\t\t\t// requiredFields and any field added to ActionDefinition later — survives the\n\t\t\t// round-trip. The graph owns topology (allowedStates/nextState/selfTransition) and the\n\t\t\t// display label. (Enumerating named fields here previously dropped clientHandler.)\n\t\t\t...existing,\n\t\t\t// The edge's label is the display name (decoupled from the key). Fall back to the\n\t\t\t// existing label, then the key, if an edge ever arrives label-less.\n\t\t\tlabel: group.label || existing?.label || actionKey,\n\t\t\t// The graph owns topology only. A self-transition (self-loop) stays in place: mark\n\t\t\t// `selfTransition`, carry NO `nextState`. A cross-state transition carries `nextState`\n\t\t\t// and clears any stale self flag (a self-loop redrawn as a normal edge). Explicit\n\t\t\t// `undefined` on the unused field is dropped by JSON.stringify, so no format churn.\n\t\t\tallowedStates: group.allowedStates,\n\t\t\tnextState: group.selfLoop ? undefined : group.nextState,\n\t\t\tselfTransition: group.selfLoop ? true : undefined,\n\t\t}\n\t}\n\n\t// Pass through Verbs (stateless: true) and global Workflow actions (no allowedStates) verbatim\n\tfor (const [actionKey, actionDef] of Object.entries(existingWorkflow?.actions ?? {})) {\n\t\tif (actionKey in transitionGroups) continue\n\t\tif (actionDef.stateless || !actionDef.allowedStates?.length) {\n\t\t\tnextActions[actionKey] = actionDef\n\t\t}\n\t\t// Workflow action with allowedStates not in graph = user deleted its edges → remove\n\t}\n\n\treturn {\n\t\t// Spread existingWorkflow first so every top-level key the graph does NOT own — the\n\t\t// sibling `triggers` map (field-validation triggers), and any WorkflowMeta key added\n\t\t// later — survives the round-trip. The graph owns topology only: states + actions,\n\t\t// overridden below. (Same principle the per-action spread applies above; enumerating\n\t\t// only states+actions here previously dropped `triggers` on every graph edit.)\n\t\tworkflow: { ...existingWorkflow, states: stateNames, actions: nextActions },\n\t\tlayout: nextLayout,\n\t}\n}\n","<template>\n\t<div>\n\t\t<NodeEditor v-model=\"elements\" :node-container-class=\"nodeContainerClass\" />\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed, onMounted } from 'vue'\nimport type { WorkflowMeta } from '@stonecrop/schema'\n\nimport NodeEditor from './NodeEditor.vue'\nimport type { FlowElements, Layout } from '../types'\nimport { autoLayout } from '../utils/autoLayout'\nimport { statesToFlowElements, flowElementsToStates } from '../utils/stateTransforms'\n\nconst workflow = defineModel<WorkflowMeta>()\nconst layout = defineModel<Layout>('layout')\nconst { nodeContainerClass = '' } = defineProps<{\n\tnodeContainerClass?: HTMLAttributes['class']\n}>()\n\nonMounted(() => {\n\tif (layout.value === undefined) {\n\t\tconsole.warn('[StateEditor] v-model:layout is not bound. Node position changes will not be persisted.')\n\t}\n})\n\nconst elements = computed<FlowElements>({\n\tget: () => {\n\t\tif (!workflow.value) return []\n\t\tconst els = statesToFlowElements(workflow.value, layout.value)\n\t\t// Seed an un-arranged workflow with an auto-computed dagre layout instead of the naive row.\n\t\t// Ephemeral: these positions are persisted only once the author drags a node (which routes\n\t\t// through flowElementsToStates → layout). A workflow with any saved layout keeps it as-is.\n\t\tconst noSavedLayout = !layout.value || Object.keys(layout.value).length === 0\n\t\treturn noSavedLayout ? autoLayout(els) : els\n\t},\n\tset: newValue => {\n\t\tconst { workflow: nextWorkflow, layout: nextLayout } = flowElementsToStates(newValue, workflow.value)\n\t\tworkflow.value = nextWorkflow\n\t\tif (layout.value !== undefined) {\n\t\t\tlayout.value = nextLayout\n\t\t}\n\t},\n})\n</script>\n","import { App } from 'vue'\n\nimport NodeEditor from './components/NodeEditor.vue'\nimport StateEditor from './components/StateEditor.vue'\nexport type * from './types'\n\n/**\n * Install all Node Editor components\n * @param app - Vue app instance\n * @public\n */\nfunction install(app: App) {\n\tapp.component('NodeEditor', NodeEditor)\n\tapp.component('StateEditor', StateEditor)\n}\n\nexport { install, NodeEditor, StateEditor }\n"],"names":["__default__","props","__props","emit","__emit","inputRef","useTemplateRef","newLabel","ref","showInput","lastClick","labelOnClick","now","showLabelInput","nextTick","submitNewLabel","path","computed","getBezierPath","_createElementVNode","_createVNode","_unref","EdgeLabelRenderer","_normalizeStyle","_cache","_withModifiers","$event","$emit","_hoisted_3","_toDisplayString","_openBlock","_createElementBlock","_hoisted_4","nodeOnClick","_hoisted_1","_createBlock","Handle","LOOP_HEIGHT","LOOP_SPREAD","sourceX","sourceY","targetX","targetY","d","labelX","labelY","autoLayout","elements","options","rankdir","nodeWidth","nodeHeight","dimensions","sizeOf","id","nodeIds","el","graph","Graph","width","height","layout","center","hover","vueFlowElements","vueFlowInstance","activeElementKey","activeElementIndex","element","items","newValue","addEdges","removeEdges","useVueFlow","onMounted","handleKeypress","onBeforeUnmount","setInstance","instance","shiftTerminal","currentTerminal","Position","shiftOutput","activeNode","emitElements","shiftInput","onWheel","event","fitView","autoArrange","store","dims","laid","positionById","position","addNode","makeEdge","newNodePosition","nodeId","edgeId","labelChanged","j","handleNodeClick","node","handleEdgeClick","edge","handleConnect","isSelfLoop","newEdge","handleEdgeContextMenu","removeEdge","_normalizeClass","_hoisted_2","_hoisted_5","VueFlow","_withCtx","EditableNode","_mergeProps","EditableEdge","SelfLoopEdge","statesToFlowElements","workflow","states","actions","edges","nodes","actionKey","actionDef","source","index","state","flowElementsToStates","nextElements","existingWorkflow","idToLabel","nextLayout","stateNames","label","transitionGroups","edgeLabel","sourceLabel","targetLabel","isSelf","nextActions","group","existing","_useModel","els","nextWorkflow","NodeEditor","install","app","StateEditor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"node-editor.js","sources":["../src/components/EditableEdge.vue","../src/components/EditableNode.vue","../src/components/SelfLoopEdge.vue","../src/utils/autoLayout.ts","../src/components/NodeEditor.vue","../src/utils/stateTransforms.ts","../src/components/StateEditor.vue","../src/index.ts"],"sourcesContent":["<template>\n\t<!-- transparent ghost path gives a ~20px click zone around the 2px visible stroke -->\n\t<path :d=\"path[0]\" fill=\"none\" stroke=\"transparent\" stroke-width=\"20\" class=\"vue-flow__edge-interaction\" />\n\t<path :id=\"id\" :style=\"style\" class=\"vue-flow__edge-path\" :d=\"path[0]\" :marker-end=\"markerEnd\" />\n\n\t<EdgeLabelRenderer>\n\t\t<div\n\t\t\t:style=\"{\n\t\t\t\tpointerEvents: 'all',\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttransform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,\n\t\t\t}\"\n\t\t\tclass=\"nodrag nopan editable-edge-label\"\n\t\t\t@click=\"labelOnClick()\"\n\t\t\t@contextmenu.prevent=\"$emit('remove', id)\">\n\t\t\t<div class=\"vue-flow__edge-label\">{{ label }}</div>\n\t\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t\t<input\n\t\t\t\t\tref=\"labelInput\"\n\t\t\t\t\tv-model=\"newLabel\"\n\t\t\t\t\tclass=\"label-input\"\n\t\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t\t</div>\n\t\t</div>\n\t</EdgeLabelRenderer>\n</template>\n\n<script setup lang=\"ts\">\nimport { type EdgeProps, EdgeLabelRenderer, getBezierPath /* useVueFlow */ } from '@vue-flow/core'\nimport { computed, ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<EdgeProps>()\nconst emit = defineEmits(['change', 'remove'])\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<EdgeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst labelOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n\nconst path = computed(() => getBezierPath(props))\n</script>\n\n<script lang=\"ts\">\nexport default {\n\tinheritAttrs: false,\n}\n</script>\n\n<style>\n.editable-edge-label {\n\tbackground-color: white;\n\tposition: relative;\n\tfont-size: 12px;\n}\n\n.label-input-wrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.label-input {\n\ttext-align: center;\n\twidth: 40ch;\n}\n</style>\n","<template>\n\t<div @click=\"nodeOnClick()\">\n\t\t<div>{{ label }}</div>\n\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t<input\n\t\t\t\tref=\"labelInput\"\n\t\t\t\tv-model=\"newLabel\"\n\t\t\t\tclass=\"label-input\"\n\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t</div>\n\t\t<Handle v-if=\"data.hasInput\" id=\"a\" type=\"target\" :position=\"targetPosition\" />\n\t\t<Handle v-if=\"data.hasOutput\" id=\"b\" type=\"source\" :position=\"sourcePosition\" />\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { NodeProps, Handle } from '@vue-flow/core'\nimport { ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<NodeProps>()\nconst emit = defineEmits(['change'])\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<NodeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst nodeOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n</script>\n\n<style>\n.label-input-wrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.label-input {\n\ttext-align: center;\n}\n</style>\n","<template>\n\t<!-- transparent ghost path gives a ~20px click zone around the 2px visible stroke -->\n\t<path :d=\"path.d\" fill=\"none\" stroke=\"transparent\" stroke-width=\"20\" class=\"vue-flow__edge-interaction\" />\n\t<path :id=\"id\" :style=\"style\" class=\"vue-flow__edge-path\" :d=\"path.d\" :marker-end=\"markerEnd\" />\n\n\t<EdgeLabelRenderer>\n\t\t<div\n\t\t\t:style=\"{\n\t\t\t\tpointerEvents: 'all',\n\t\t\t\tposition: 'absolute',\n\t\t\t\ttransform: `translate(-50%, -50%) translate(${path.labelX}px,${path.labelY}px)`,\n\t\t\t}\"\n\t\t\tclass=\"nodrag nopan editable-edge-label\"\n\t\t\t@click=\"labelOnClick()\"\n\t\t\t@contextmenu.prevent=\"$emit('remove', id)\">\n\t\t\t<div class=\"vue-flow__edge-label\">{{ label }}</div>\n\t\t\t<div v-if=\"showInput\" class=\"label-input-wrapper\">\n\t\t\t\t<input\n\t\t\t\t\tref=\"labelInput\"\n\t\t\t\t\tv-model=\"newLabel\"\n\t\t\t\t\tclass=\"label-input\"\n\t\t\t\t\t@blur=\"showInput = false\"\n\t\t\t\t\t@keypress.enter=\"submitNewLabel\" />\n\t\t\t</div>\n\t\t</div>\n\t</EdgeLabelRenderer>\n</template>\n\n<script setup lang=\"ts\">\nimport { type EdgeProps, EdgeLabelRenderer } from '@vue-flow/core'\nimport { computed, ref, nextTick, useTemplateRef } from 'vue'\n\nconst props = defineProps<EdgeProps>()\nconst emit = defineEmits(['change', 'remove'])\n\n// A self-loop connects a node's source handle to its own target handle. getBezierPath draws a nearly\n// straight segment across the node for that (the two handles are on the same box), so it's useless\n// here — we hand-author an arc that leaves the source handle, loops up and over the node top, and\n// returns to the target handle. LOOP_HEIGHT is how far above the handles the arc bulges.\nconst LOOP_HEIGHT = 90\nconst LOOP_SPREAD = 45\n\nconst path = computed(() => {\n\tconst { sourceX, sourceY, targetX, targetY } = props\n\tconst d = `M ${sourceX},${sourceY} C ${sourceX + LOOP_SPREAD},${sourceY - LOOP_HEIGHT} ${\n\t\ttargetX - LOOP_SPREAD\n\t},${targetY - LOOP_HEIGHT} ${targetX},${targetY}`\n\t// Place the label near the arc's apex (a cubic bezier peaks around 0.75 of the control offset).\n\tconst labelX = (sourceX + targetX) / 2\n\tconst labelY = Math.min(sourceY, targetY) - LOOP_HEIGHT * 0.72\n\treturn { d, labelX, labelY }\n})\n\nconst inputRef = useTemplateRef<HTMLInputElement>('labelInput')\nconst newLabel = ref<EdgeProps['label']>('')\nconst showInput = ref(false)\nlet lastClick = 0\n\nconst labelOnClick = async () => {\n\tlet now = Date.now()\n\tif (now - lastClick < 500 && !showInput.value) {\n\t\tawait showLabelInput()\n\t}\n\tlastClick = now\n}\n\nconst showLabelInput = async () => {\n\tnewLabel.value = props.label\n\tshowInput.value = true\n\tawait nextTick()\n\tinputRef.value?.focus()\n}\n\nconst submitNewLabel = () => {\n\tshowInput.value = false\n\temit('change', newLabel.value)\n}\n</script>\n\n<script lang=\"ts\">\nexport default {\n\tinheritAttrs: false,\n}\n</script>\n\n<style>\n/* Label + input styles are shared with EditableEdge (defined there, global scope). */\n</style>\n","import { Graph, layout } from '@dagrejs/dagre'\n\nimport type { FlowElements } from '../types'\n\n/**\n * Options for {@link autoLayout}.\n * @public\n */\nexport interface AutoLayoutOptions {\n\t/** Layout direction. Defaults to `'LR'` to match the editor's Left/Right handle defaults. */\n\trankdir?: 'LR' | 'RL' | 'TB' | 'BT'\n\t/** Fallback node width when no measured size is supplied (the seed path has no DOM to measure). */\n\tnodeWidth?: number\n\t/** Fallback node height when no measured size is supplied. */\n\tnodeHeight?: number\n\t/** Measured per-node sizes (node id → box) — supplied by the on-demand \"Auto-arrange\" button. */\n\tdimensions?: Record<string, { width: number; height: number }>\n}\n\n/**\n * Compute node positions for a workflow graph with dagre's layered (Sugiyama) algorithm.\n *\n * Pure and synchronous: takes VueFlow elements (nodes + edges) and returns a new elements array with\n * each node's `position` replaced by a laid-out coordinate; edges and every other node field are\n * passed through untouched. Used two ways — as the seed for an un-arranged workflow (fixed default\n * dimensions, no DOM) and behind the toolbar button (measured `dimensions`).\n *\n * Self-loop edges (`source === target`) are skipped: dagre doesn't rank them, and they're reserved\n * for the separate mutate-in-place self-transition feature.\n * @public\n */\nexport function autoLayout(elements: FlowElements, options: AutoLayoutOptions = {}): FlowElements {\n\tconst { rankdir = 'LR', nodeWidth = 160, nodeHeight = 40, dimensions } = options\n\tconst sizeOf = (id: string) => dimensions?.[id] ?? { width: nodeWidth, height: nodeHeight }\n\n\t// Nodes are the elements without a `source` (the same discriminator flowElementsToStates uses).\n\tconst nodeIds: string[] = []\n\tfor (const el of elements) {\n\t\tif (!('source' in el)) nodeIds.push(el.id)\n\t}\n\tif (nodeIds.length === 0) return [...elements]\n\n\tconst graph = new Graph()\n\tgraph.setGraph({ rankdir, nodesep: 40, ranksep: 80, edgesep: 20 })\n\tgraph.setDefaultEdgeLabel(() => ({}))\n\n\tfor (const id of nodeIds) {\n\t\tconst { width, height } = sizeOf(id)\n\t\tgraph.setNode(id, { width, height })\n\t}\n\tfor (const el of elements) {\n\t\tif (!('source' in el)) continue\n\t\tif (el.source === el.target) continue\n\t\tgraph.setEdge(el.source, el.target)\n\t}\n\n\tlayout(graph)\n\n\t// dagre reports each node by its CENTER; VueFlow positions nodes by their TOP-LEFT corner.\n\treturn elements.map(el => {\n\t\tif ('source' in el) return el\n\t\tconst center = graph.node(el.id)\n\t\tif (!center) return el\n\t\tconst { width, height } = sizeOf(el.id)\n\t\treturn { ...el, position: { x: center.x - width / 2, y: center.y - height / 2 } }\n\t})\n}\n","<template>\n\t<div\n\t\tclass=\"node-editor-wrapper\"\n\t\t:class=\"nodeContainerClass\"\n\t\t@contextmenu.prevent\n\t\t@mouseover=\"hover = true\"\n\t\t@mouseleave=\"hover = false\">\n\t\t<div class=\"chart-controls\">\n\t\t\t<div class=\"chart-controls-left\">\n\t\t\t\t<div><b>Selected Node:</b> {{ activeElementKey ? activeElementKey : 'none' }}</div>\n\t\t\t</div>\n\t\t\t<div class=\"chart-controls-right\">\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"addNode\">Add Node</button>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"fitView\">Center</button>\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<button class=\"button-default\" @click=\"autoArrange\">Auto-arrange</button>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"activeElementIndex > -1\">\n\t\t\t\t\t<button class=\"button-default\" @click=\"shiftInput\">Shift Input Position</button>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"activeElementIndex > -1\">\n\t\t\t\t\t<button class=\"button-default\" @click=\"shiftOutput\">Shift Output Position</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<VueFlow\n\t\t\tv-if=\"vueFlowElements && vueFlowElements.length\"\n\t\t\tv-model=\"vueFlowElements\"\n\t\t\tclass=\"nowheel\"\n\t\t\t:prevent-scrolling=\"true\"\n\t\t\t:zoom-on-scroll=\"false\"\n\t\t\t:fit-view-on-init=\"true\"\n\t\t\t:pan-activation-key-code=\"null\"\n\t\t\t@connect=\"handleConnect\"\n\t\t\t@pane-ready=\"setInstance\"\n\t\t\t@node-click=\"handleNodeClick\"\n\t\t\t@edge-click=\"handleEdgeClick\"\n\t\t\t@edge-context-menu=\"handleEdgeContextMenu\"\n\t\t\t@node-drag-stop=\"emitElements\"\n\t\t\t@wheel.prevent=\"onWheel\">\n\t\t\t<template #node-editable=\"props\">\n\t\t\t\t<EditableNode v-bind=\"props\" @change=\"labelChanged($event, props.id)\" />\n\t\t\t</template>\n\t\t\t<template #edge-editable=\"props\">\n\t\t\t\t<EditableEdge v-bind=\"props\" @change=\"labelChanged($event, props.id)\" @remove=\"removeEdge(props.id)\" />\n\t\t\t</template>\n\t\t\t<template #edge-selfloop=\"props\">\n\t\t\t\t<SelfLoopEdge v-bind=\"props\" @change=\"labelChanged($event, props.id)\" @remove=\"removeEdge(props.id)\" />\n\t\t\t</template>\n\t\t</VueFlow>\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n\ttype VueFlowStore,\n\tPosition,\n\tVueFlow,\n\tuseVueFlow,\n\tConnection,\n\tNode,\n\tNodeMouseEvent,\n\tEdgeMouseEvent,\n\tDefaultEdge,\n} from '@vue-flow/core'\nimport { type HTMLAttributes, ref, computed, nextTick, onBeforeUnmount, onMounted } from 'vue'\n\nimport EditableEdge from './EditableEdge.vue'\nimport EditableNode from './EditableNode.vue'\nimport SelfLoopEdge from './SelfLoopEdge.vue'\nimport { autoLayout } from '../utils/autoLayout'\nimport type { FlowElements } from '../types'\n\nconst { modelValue, nodeContainerClass = '' } = defineProps<{\n\tmodelValue: FlowElements\n\tnodeContainerClass?: HTMLAttributes['class']\n}>()\nconst emit = defineEmits(['update:modelValue'])\n\nconst hover = ref(false)\nconst vueFlowElements = ref<FlowElements>([])\nconst vueFlowInstance = ref<VueFlowStore>()\n\nconst activeElementKey = ref('')\nconst activeElementIndex = computed(() =>\n\tvueFlowElements.value.findIndex(element => element.id === activeElementKey.value)\n)\n\nconst elements = computed({\n\tget: () => {\n\t\tconst items = modelValue\n\n\t\t// Add rendering flags without clobbering caller-provided data. Edges carry `data.actionKey`\n\t\t// (the stable action identity from stateTransforms); wiping data here would drop it before it\n\t\t// round-trips back through emitElements, silently re-keying actions on every graph edit.\n\t\tfor (const element of items) {\n\t\t\telement.data = { ...element.data }\n\t\t\tif (element.type === 'input') {\n\t\t\t\telement.data.hasInput = false\n\t\t\t\telement.data.hasOutput = true\n\t\t\t} else if (element.type === 'output') {\n\t\t\t\telement.data.hasInput = true\n\t\t\t\telement.data.hasOutput = false\n\t\t\t} else {\n\t\t\t\telement.data.hasInput = true\n\t\t\t\telement.data.hasOutput = true\n\t\t\t}\n\t\t\telement.class = 'vue-flow__node-default'\n\t\t\t// A self-loop edge (source === target) routes to the SelfLoopEdge arc renderer; everything\n\t\t\t// else (nodes and cross-state edges) uses the default editable slot. getBezierPath draws a\n\t\t\t// useless near-straight segment for a self-loop, so it must not fall through to 'editable'.\n\t\t\telement.type = 'source' in element && element.source === element.target ? 'selfloop' : 'editable'\n\t\t}\n\n\t\treturn items\n\t},\n\tset: newValue => {\n\t\temit('update:modelValue', JSON.parse(JSON.stringify(newValue)))\n\t},\n})\nconst { addEdges, removeEdges } = useVueFlow()\n\nonMounted(() => {\n\tdocument.removeEventListener('keypress', handleKeypress)\n\tdocument.addEventListener('keypress', handleKeypress)\n})\n\nonBeforeUnmount(() => {\n\tdocument.removeEventListener('keypress', handleKeypress)\n})\n\nconst setInstance = (instance: VueFlowStore) => {\n\tvueFlowInstance.value = instance\n}\n\nvueFlowElements.value = elements.value\n\n// Methods\nconst shiftTerminal = (currentTerminal: Position) => {\n\treturn {\n\t\t[Position.Top]: Position.Right,\n\t\t[Position.Right]: Position.Bottom,\n\t\t[Position.Bottom]: Position.Left,\n\t\t[Position.Left]: Position.Top,\n\t}[currentTerminal]\n}\n\nconst shiftOutput = () => {\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value] as Node\n\t\tif (!activeNode.sourcePosition) return\n\t\tactiveNode.sourcePosition = shiftTerminal(activeNode.sourcePosition)\n\t\temitElements()\n\t}\n}\n\nconst shiftInput = () => {\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value] as Node\n\t\tif (!activeNode.targetPosition) return\n\t\tactiveNode.targetPosition = shiftTerminal(activeNode.targetPosition)\n\t\temitElements()\n\t}\n}\n\nconst onWheel = (event: WheelEvent) => {\n\twindow.scrollBy(0, event.deltaY)\n}\n\nconst handleKeypress = (event: KeyboardEvent) => {\n\tif (hover.value && event.ctrlKey == true) {\n\t\tif (event.key == '+' || event.key == '=') {\n\t\t\tvoid vueFlowInstance.value?.zoomIn()\n\t\t}\n\t\tif (event.key == '-') {\n\t\t\tvoid vueFlowInstance.value?.zoomOut()\n\t\t}\n\t}\n}\n\nconst fitView = async () => {\n\tawait vueFlowInstance.value?.fitView()\n}\n\nconst autoArrange = async () => {\n\t// Read measured node sizes from the VueFlow store so the layout fits actual box widths (state\n\t// labels differ in length); autoLayout falls back to default dimensions for any unmeasured node.\n\tconst store = vueFlowInstance.value\n\tconst dimensions: Record<string, { width: number; height: number }> = {}\n\tfor (const el of vueFlowElements.value) {\n\t\tif ('source' in el) continue\n\t\tconst dims = store?.findNode?.(el.id)?.dimensions\n\t\tif (dims?.width && dims?.height) dimensions[el.id] = { width: dims.width, height: dims.height }\n\t}\n\n\tconst laid = autoLayout(vueFlowElements.value, { dimensions })\n\tconst positionById = new Map<string, { x: number; y: number }>()\n\tfor (const el of laid) {\n\t\tif ('source' in el) continue\n\t\tpositionById.set(el.id, el.position)\n\t}\n\t// Apply positions onto the v-model elements — VueFlow reacts to these, same as shiftInput/Output.\n\tfor (const el of vueFlowElements.value) {\n\t\tif ('source' in el) continue\n\t\tconst position = positionById.get(el.id)\n\t\tif (position) el.position = position\n\t}\n\n\temitElements()\n\tawait nextTick()\n\tawait fitView()\n}\n\nconst addNode = () => {\n\tlet makeEdge = false\n\tlet newNodePosition = { x: Math.random() * 200, y: Math.random() * 200 }\n\tif (activeElementIndex.value > -1) {\n\t\tconst activeNode = vueFlowElements.value[activeElementIndex.value]\n\t\tif (activeNode.data?.hasOutput) {\n\t\t\tnewNodePosition = { x: (activeNode as Node).position.x + 200, y: (activeNode as Node).position.y + 50 }\n\t\t\tmakeEdge = true\n\t\t}\n\t}\n\n\tconst id = vueFlowElements.value.length\n\tconst nodeId = `node-${id}`\n\tvueFlowElements.value.push({\n\t\tid: nodeId,\n\t\tlabel: 'Node ' + id,\n\t\tsourcePosition: Position.Right,\n\t\ttargetPosition: Position.Left,\n\t\tclass: 'vue-flow__node-default',\n\t\ttype: 'editable',\n\t\tdata: {\n\t\t\thasInput: true,\n\t\t\thasOutput: true,\n\t\t},\n\t\tposition: newNodePosition,\n\t})\n\n\tif (makeEdge) {\n\t\tconst edgeId = `edge-${id + 1}`\n\t\tvueFlowElements.value.push({\n\t\t\tid: edgeId,\n\t\t\tsource: activeElementKey.value,\n\t\t\ttarget: nodeId,\n\t\t\ttype: 'editable',\n\t\t\tlabel: `EDGE ${id + 1}`,\n\t\t\tanimated: true,\n\t\t})\n\t}\n\temitElements()\n}\n\nconst labelChanged = (event: DefaultEdge['label'], id: DefaultEdge['id']) => {\n\tfor (let j = 0; j < vueFlowElements.value.length; j++) {\n\t\tif (vueFlowElements.value[j].id == id) {\n\t\t\tvueFlowElements.value[j].label = event\n\t\t\tbreak\n\t\t}\n\t}\n\temitElements()\n}\n\nconst handleNodeClick = ({ node }: NodeMouseEvent) => {\n\tactiveElementKey.value = node.id\n}\n\nconst handleEdgeClick = ({ edge }: EdgeMouseEvent) => {\n\tactiveElementKey.value = edge.id\n}\n\nconst handleConnect = async (event: Connection) => {\n\tconst id = vueFlowElements.value.length\n\t// A node connected to itself is a self-transition (mutate-in-place) — render it as a loop.\n\tconst isSelfLoop = event.source === event.target\n\tconst newEdge = {\n\t\tid: `edge-${id}`,\n\t\tsource: event.source,\n\t\ttarget: event.target,\n\t\ttype: isSelfLoop ? 'selfloop' : 'editable',\n\t\tlabel: `New Edge`,\n\t\tinteractionWidth: 400,\n\t\tanimated: true,\n\t}\n\taddEdges([newEdge])\n\tawait nextTick()\n\temitElements()\n}\n\nconst handleEdgeContextMenu = async (event: EdgeMouseEvent) => {\n\tremoveEdges([event.edge.id])\n\tawait nextTick()\n\temitElements()\n}\n\nconst removeEdge = async (id: string) => {\n\tremoveEdges([id])\n\tawait nextTick()\n\temitElements()\n}\n\nconst emitElements = () => {\n\temit('update:modelValue', JSON.parse(JSON.stringify(vueFlowElements.value)))\n}\n</script>\n\n<style>\n@import '@vue-flow/core/dist/style.css';\n@import '@vue-flow/core/dist/theme-default.css';\n\n.chart-controls-left,\n.chart-controls-right {\n\theight: 1.8em;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tpadding-top: 0.2em;\n}\n\n.chart-controls-right div {\n\tmargin-left: 5px;\n}\n\n.chart-controls {\n\tposition: absolute;\n\tbottom: 0.5rem;\n\tleft: 0.5rem;\n\tz-index: 10;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\tgap: 0.35rem;\n\tpadding: 0.4rem 0.5rem;\n\tbackground: rgba(255, 255, 255, 0.92);\n\tborder: 1px solid #ccc;\n\tborder-radius: 4px;\n\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.chart-controls div {\n\tmargin-bottom: 0;\n}\n\n.defaultContainerClass {\n\theight: 90vh;\n\twidth: 100%;\n\tborder: 1px solid #ccc;\n}\n\n.default-input-node.vue-flow__node-input,\n.default-output-node.vue-flow__node-output {\n\tborder-color: #000;\n}\n\n.default-input-node.vue-flow__node-input .vue-flow__handle,\n.default-output-node.vue-flow__node-output .vue-flow__handle {\n\tbackground-color: #000;\n}\n\n.default-input-node.vue-flow__node-input.selected,\n.default-output-node.vue-flow__node-output.selected {\n\tbox-shadow: 0 0 0 0.5px #000;\n}\n\nbutton.button-default {\n\tbackground-color: #ffffff;\n\tpadding: 1px 12px;\n\tborder-radius: 3px;\n\tborder: 1px solid #ccc;\n\tcursor: pointer;\n\twhite-space: nowrap;\n}\n\nbutton.button-default:hover {\n\tbackground-color: #f2f2f2;\n}\n\n.vue-flow {\n\tbackground-size: 40px 40px;\n\tbackground-image:\n\t\tlinear-gradient(to right, #ccc 1px, transparent 1px), linear-gradient(to bottom, #ccc 1px, transparent 1px);\n}\n\ninput.label-editor {\n\tposition: absolute;\n}\n\n.node-editor-wrapper {\n\tposition: relative;\n}\n</style>\n","import { Position, type Node } from '@vue-flow/core'\nimport type { ActionDefinition, WorkflowMeta } from '@stonecrop/schema'\n\nimport type { FlowElements, Layout } from '../types'\n\nexport function statesToFlowElements(workflow: WorkflowMeta, layout?: Layout): FlowElements {\n\tconst { states = [], actions = {} } = workflow\n\tconst edges: FlowElements = []\n\tconst nodes: Node[] = []\n\n\tfor (const [actionKey, actionDef] of Object.entries(actions)) {\n\t\t// Stateless commands (print/email) have no graph presence; anything graph-owned needs states.\n\t\tif (actionDef.stateless || !actionDef.allowedStates?.length) continue\n\n\t\t// A self-transition (mutate-in-place `save`) renders as a self-loop on each allowed state:\n\t\t// `source === target`, tagged `selfloop` so NodeEditor routes it to the arc renderer.\n\t\tif (actionDef.selfTransition) {\n\t\t\tfor (const source of actionDef.allowedStates) {\n\t\t\t\tedges.push({\n\t\t\t\t\tid: `${actionKey}-${source}`,\n\t\t\t\t\tsource,\n\t\t\t\t\ttarget: source,\n\t\t\t\t\tlabel: actionDef.label ?? actionKey,\n\t\t\t\t\tdata: { actionKey },\n\t\t\t\t\tanimated: true,\n\t\t\t\t\ttype: 'selfloop',\n\t\t\t\t\tinteractionWidth: 40,\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// A cross-state transition needs a target; a malformed action with neither is skipped.\n\t\tif (!actionDef.nextState) continue\n\t\tfor (const source of actionDef.allowedStates) {\n\t\t\tedges.push({\n\t\t\t\tid: `${actionKey}-${source}`,\n\t\t\t\tsource,\n\t\t\t\ttarget: actionDef.nextState,\n\t\t\t\t// The edge paints the human display label; its identity (the action key) rides in\n\t\t\t\t// `data.actionKey`, so relabeling the edge renames the action without re-keying it.\n\t\t\t\tlabel: actionDef.label ?? actionKey,\n\t\t\t\tdata: { actionKey },\n\t\t\t\tanimated: true,\n\t\t\t\ttype: 'smoothstep',\n\t\t\t\tinteractionWidth: 40,\n\t\t\t})\n\t\t}\n\t}\n\n\tfor (let index = 0; index < states.length; index++) {\n\t\tconst state = states[index]\n\t\tconst node: Node = {\n\t\t\tid: state,\n\t\t\tlabel: state,\n\t\t\tposition: layout?.[state]?.position ?? { x: 200 * index, y: 100 },\n\t\t\ttargetPosition: layout?.[state]?.targetPosition ?? Position.Left,\n\t\t\tsourcePosition: layout?.[state]?.sourcePosition ?? Position.Right,\n\t\t}\n\t\t// Every state renders identically — both handles, no start-state styling — so any transition\n\t\t// (including a returning `reject`/`reopen` into the initial state) is authorable and a\n\t\t// self-loop can anchor both ends. Marking an entry state is deferred (YAGNI) until needed.\n\t\tnodes.push(node)\n\t}\n\n\treturn [...edges, ...nodes]\n}\n\nexport function flowElementsToStates(\n\tnextElements: FlowElements,\n\texistingWorkflow?: WorkflowMeta\n): { workflow: WorkflowMeta; layout: Layout } {\n\tconst idToLabel: Record<string, string> = {}\n\tconst nextLayout: Layout = {}\n\tconst stateNames: string[] = []\n\n\tfor (const el of nextElements) {\n\t\tif ('source' in el) continue\n\t\tconst label = typeof el.label === 'string' ? el.label : el.id\n\t\tidToLabel[el.id] = label\n\t\tstateNames.push(label)\n\t\tif (el.position) {\n\t\t\tnextLayout[label] = {\n\t\t\t\tposition: el.position,\n\t\t\t\t...(el.targetPosition !== undefined && { targetPosition: el.targetPosition }),\n\t\t\t\t...(el.sourcePosition !== undefined && { sourcePosition: el.sourcePosition }),\n\t\t\t}\n\t\t}\n\t}\n\n\t// Group directed edges by their stable action key. A round-tripped edge carries the key in\n\t// `data.actionKey`; a freshly-drawn edge (no data yet) falls back to its label as the key — the\n\t// one moment label and key coincide, when the action is first born. The edge's label is captured\n\t// separately as the display name, so a later relabel renames the action without re-keying it.\n\tconst transitionGroups: Record<\n\t\tstring,\n\t\t{ nextState?: string; allowedStates: string[]; label: string; selfLoop: boolean }\n\t> = {}\n\tfor (const el of nextElements) {\n\t\tif (!('source' in el)) continue\n\t\tconst edgeLabel = typeof el.label === 'string' ? el.label : el.id\n\t\tconst actionKey = el.data?.actionKey ?? edgeLabel\n\t\tconst sourceLabel = idToLabel[el.source] || el.source\n\t\tconst targetLabel = idToLabel[el.target] || el.target\n\t\t// Classify by topology, not by edge `type`: a self-loop (source === target) round-trips to a\n\t\t// self-transition regardless of how it was authored (drawn node→itself, or re-rendered from a\n\t\t// `selfTransition` action). A group's kind is set by its first edge; a multi-state self-loop\n\t\t// (e.g. `save` on Draft AND Pending) accumulates each source into allowedStates.\n\t\tconst isSelf = el.source === el.target\n\t\tif (!transitionGroups[actionKey]) {\n\t\t\ttransitionGroups[actionKey] = {\n\t\t\t\tallowedStates: [sourceLabel],\n\t\t\t\tlabel: edgeLabel,\n\t\t\t\tselfLoop: isSelf,\n\t\t\t\t...(isSelf ? {} : { nextState: targetLabel }),\n\t\t\t}\n\t\t} else {\n\t\t\ttransitionGroups[actionKey].allowedStates.push(sourceLabel)\n\t\t}\n\t}\n\n\tconst nextActions: Record<string, ActionDefinition> = {}\n\n\t// Transitions (and self-transitions) derived from graph edges\n\tfor (const [actionKey, group] of Object.entries(transitionGroups)) {\n\t\tconst existing = existingWorkflow?.actions?.[actionKey]\n\t\tnextActions[actionKey] = {\n\t\t\t// Spread existing first so every field the graph does NOT own — clientHandler,\n\t\t\t// requiredFields and any field added to ActionDefinition later — survives the\n\t\t\t// round-trip. The graph owns topology (allowedStates/nextState/selfTransition) and the\n\t\t\t// display label. (Enumerating named fields here previously dropped clientHandler.)\n\t\t\t...existing,\n\t\t\t// The edge's label is the display name (decoupled from the key). Fall back to the\n\t\t\t// existing label, then the key, if an edge ever arrives label-less.\n\t\t\tlabel: group.label || existing?.label || actionKey,\n\t\t\t// The graph owns topology only. A self-transition (self-loop) stays in place: mark\n\t\t\t// `selfTransition`, carry NO `nextState`. A cross-state transition carries `nextState`\n\t\t\t// and clears any stale self flag (a self-loop redrawn as a normal edge). Explicit\n\t\t\t// `undefined` on the unused field is dropped by JSON.stringify, so no format churn.\n\t\t\tallowedStates: group.allowedStates,\n\t\t\tnextState: group.selfLoop ? undefined : group.nextState,\n\t\t\tselfTransition: group.selfLoop ? true : undefined,\n\t\t}\n\t}\n\n\t// Pass through Verbs (stateless: true) and global Workflow actions (no allowedStates) verbatim\n\tfor (const [actionKey, actionDef] of Object.entries(existingWorkflow?.actions ?? {})) {\n\t\tif (actionKey in transitionGroups) continue\n\t\tif (actionDef.stateless || !actionDef.allowedStates?.length) {\n\t\t\tnextActions[actionKey] = actionDef\n\t\t}\n\t\t// Workflow action with allowedStates not in graph = user deleted its edges → remove\n\t}\n\n\treturn {\n\t\t// Spread existingWorkflow first so every top-level key the graph does NOT own — the\n\t\t// sibling `triggers` map (field-validation triggers), and any WorkflowMeta key added\n\t\t// later — survives the round-trip. The graph owns topology only: states + actions,\n\t\t// overridden below. (Same principle the per-action spread applies above; enumerating\n\t\t// only states+actions here previously dropped `triggers` on every graph edit.)\n\t\tworkflow: { ...existingWorkflow, states: stateNames, actions: nextActions },\n\t\tlayout: nextLayout,\n\t}\n}\n","<template>\n\t<div>\n\t\t<NodeEditor v-model=\"elements\" :node-container-class=\"nodeContainerClass\" />\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed, onMounted } from 'vue'\nimport type { WorkflowMeta } from '@stonecrop/schema'\n\nimport NodeEditor from './NodeEditor.vue'\nimport type { FlowElements, Layout } from '../types'\nimport { autoLayout } from '../utils/autoLayout'\nimport { statesToFlowElements, flowElementsToStates } from '../utils/stateTransforms'\n\nconst workflow = defineModel<WorkflowMeta>()\nconst layout = defineModel<Layout>('layout')\nconst { nodeContainerClass = '' } = defineProps<{\n\tnodeContainerClass?: HTMLAttributes['class']\n}>()\n\nonMounted(() => {\n\tif (layout.value === undefined) {\n\t\tconsole.warn('[StateEditor] v-model:layout is not bound. Node position changes will not be persisted.')\n\t}\n})\n\nconst elements = computed<FlowElements>({\n\tget: () => {\n\t\tif (!workflow.value) return []\n\t\tconst els = statesToFlowElements(workflow.value, layout.value)\n\t\t// Seed an un-arranged workflow with an auto-computed dagre layout instead of the naive row.\n\t\t// Ephemeral: these positions are persisted only once the author drags a node (which routes\n\t\t// through flowElementsToStates → layout). A workflow with any saved layout keeps it as-is.\n\t\tconst noSavedLayout = !layout.value || Object.keys(layout.value).length === 0\n\t\treturn noSavedLayout ? autoLayout(els) : els\n\t},\n\tset: newValue => {\n\t\tconst { workflow: nextWorkflow, layout: nextLayout } = flowElementsToStates(newValue, workflow.value)\n\t\tworkflow.value = nextWorkflow\n\t\tif (layout.value !== undefined) {\n\t\t\tlayout.value = nextLayout\n\t\t}\n\t},\n})\n</script>\n","import { App } from 'vue'\n\nimport NodeEditor from './components/NodeEditor.vue'\nimport StateEditor from './components/StateEditor.vue'\nexport type * from './types'\n\n// `Layout` types its handle placement as this enum, so a consumer cannot fill that field without\n// naming it. It is an enum rather than a string union, which makes the obvious `'left'` a type\n// error, and @vue-flow/core is a transitive dependency a consumer should not have to add.\nexport { Position } from '@vue-flow/core'\n\n/**\n * Install all Node Editor components\n * @param app - Vue app instance\n * @public\n */\nfunction install(app: App) {\n\tapp.component('NodeEditor', NodeEditor)\n\tapp.component('StateEditor', StateEditor)\n}\n\nexport { install, NodeEditor, StateEditor }\n"],"names":["__default__","props","__props","emit","__emit","inputRef","useTemplateRef","newLabel","ref","showInput","lastClick","labelOnClick","now","showLabelInput","nextTick","submitNewLabel","path","computed","getBezierPath","_createElementVNode","_createVNode","_unref","EdgeLabelRenderer","_normalizeStyle","_cache","_withModifiers","$event","$emit","_hoisted_3","_toDisplayString","_openBlock","_createElementBlock","_hoisted_4","nodeOnClick","_hoisted_1","_createBlock","Handle","LOOP_HEIGHT","LOOP_SPREAD","sourceX","sourceY","targetX","targetY","d","labelX","labelY","autoLayout","elements","options","rankdir","nodeWidth","nodeHeight","dimensions","sizeOf","id","nodeIds","el","graph","Graph","width","height","layout","center","hover","vueFlowElements","vueFlowInstance","activeElementKey","activeElementIndex","element","items","newValue","addEdges","removeEdges","useVueFlow","onMounted","handleKeypress","onBeforeUnmount","setInstance","instance","shiftTerminal","currentTerminal","Position","shiftOutput","activeNode","emitElements","shiftInput","onWheel","event","fitView","autoArrange","store","dims","laid","positionById","position","addNode","makeEdge","newNodePosition","nodeId","edgeId","labelChanged","j","handleNodeClick","node","handleEdgeClick","edge","handleConnect","isSelfLoop","newEdge","handleEdgeContextMenu","removeEdge","_normalizeClass","_hoisted_2","_hoisted_5","VueFlow","_withCtx","EditableNode","_mergeProps","EditableEdge","SelfLoopEdge","statesToFlowElements","workflow","states","actions","edges","nodes","actionKey","actionDef","source","index","state","flowElementsToStates","nextElements","existingWorkflow","idToLabel","nextLayout","stateNames","label","transitionGroups","edgeLabel","sourceLabel","targetLabel","isSelf","nextActions","group","existing","_useModel","els","nextWorkflow","NodeEditor","install","app","StateEditor"],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { App } from 'vue';
|
|
|
2
2
|
import NodeEditor from './components/NodeEditor.vue';
|
|
3
3
|
import StateEditor from './components/StateEditor.vue';
|
|
4
4
|
export type * from './types';
|
|
5
|
+
export { Position } from '@vue-flow/core';
|
|
5
6
|
/**
|
|
6
7
|
* Install all Node Editor components
|
|
7
8
|
* @param app - Vue app instance
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,mBAAmB,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,mBAAmB,SAAS,CAAA;AAK5B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC;;;;GAIG;AACH,iBAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAGxB;AAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import NodeEditor from './components/NodeEditor.vue';
|
|
2
2
|
import StateEditor from './components/StateEditor.vue';
|
|
3
|
+
// `Layout` types its handle placement as this enum, so a consumer cannot fill that field without
|
|
4
|
+
// naming it. It is an enum rather than a string union, which makes the obvious `'left'` a type
|
|
5
|
+
// error, and @vue-flow/core is a transitive dependency a consumer should not have to add.
|
|
6
|
+
export { Position } from '@vue-flow/core';
|
|
3
7
|
/**
|
|
4
8
|
* Install all Node Editor components
|
|
5
9
|
* @param app - Vue app instance
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/node-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Node editor UI for Stonecrop",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/agritheory/stonecrop/issues"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@dagrejs/dagre": "^3.0.0",
|
|
37
37
|
"@vue-flow/core": "^1.48.1",
|
|
38
|
-
"@stonecrop/schema": "0.
|
|
38
|
+
"@stonecrop/schema": "0.31.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@microsoft/api-documenter": "^7.30.5",
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,11 @@ import NodeEditor from './components/NodeEditor.vue'
|
|
|
4
4
|
import StateEditor from './components/StateEditor.vue'
|
|
5
5
|
export type * from './types'
|
|
6
6
|
|
|
7
|
+
// `Layout` types its handle placement as this enum, so a consumer cannot fill that field without
|
|
8
|
+
// naming it. It is an enum rather than a string union, which makes the obvious `'left'` a type
|
|
9
|
+
// error, and @vue-flow/core is a transitive dependency a consumer should not have to add.
|
|
10
|
+
export { Position } from '@vue-flow/core'
|
|
11
|
+
|
|
7
12
|
/**
|
|
8
13
|
* Install all Node Editor components
|
|
9
14
|
* @param app - Vue app instance
|