@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.
@@ -53,6 +53,8 @@ export declare type Layout = {
53
53
 
54
54
  export { NodeEditor }
55
55
 
56
+ export { Position }
57
+
56
58
  export { StateEditor }
57
59
 
58
60
  export { }
@@ -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 L, createBlock as H, onMounted as Z, onBeforeUnmount as ie, normalizeClass as ue, createTextVNode as de, mergeProps as A, useModel as J, mergeModels as re } from "vue";
2
- import { getBezierPath as ce, EdgeLabelRenderer as ee, Handle as q, useVueFlow as ve, VueFlow as fe, Position as C } from "@vue-flow/core";
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: v }) {
46
- const r = l, p = v, n = Y("labelInput"), u = E(""), t = E(!1);
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 f = Date.now();
50
- f - e < 500 && !t.value && await s(), e = f;
50
+ let v = Date.now();
51
+ v - e < 500 && !t.value && await s(), e = v;
51
52
  }, s = async () => {
52
- u.value = r.label, t.value = !0, await L(), n.value?.focus();
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(r));
56
- return (f, y) => (S(), P(Q, null, [
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) => f.$emit("remove", l.id), ["prevent"]))
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: v }) {
129
- const r = l, p = v, n = Y("labelInput"), u = E(""), t = E(!1);
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 = r.label, t.value = !0, await L(), n.value?.focus();
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, f) => (S(), P("div", {
140
- onClick: f[2] || (f[2] = (y) => a())
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": f[0] || (f[0] = (y) => u.value = y),
147
+ "onUpdate:modelValue": v[0] || (v[0] = (y) => u.value = y),
147
148
  class: "label-input",
148
- onBlur: f[1] || (f[1] = (y) => t.value = !1),
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
- }, Ie = /* @__PURE__ */ T({
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: v }) {
210
- const r = l, p = v, n = 90, u = 45, t = M(() => {
211
- const { sourceX: h, sourceY: k, targetX: $, targetY: x } = r, j = `M ${h},${k} C ${h + u},${k - n} ${$ - u},${x - n} ${$},${x}`, z = (h + $) / 2, V = Math.min(k, x) - n * 0.72;
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 f(), g = h;
218
- }, f = async () => {
219
- a.value = r.label, s.value = !0, await L(), e.value?.focus();
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, v = {}) {
270
- const { rankdir: r = "LR", nodeWidth: p = 160, nodeHeight: n = 40, dimensions: u } = v, t = (s) => u?.[s] ?? { width: p, height: n }, e = [];
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: r, nodesep: 40, ranksep: 80, edgesep: 20 }), a.setDefaultEdgeLabel(() => ({}));
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: f } = t(s.id);
287
- return { ...s, position: { x: g.x - m / 2, y: g.y - f / 2 } };
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 Le = { class: "chart-controls" }, xe = { class: "chart-controls-left" }, Oe = { class: "chart-controls-right" }, Ve = { key: 0 }, Re = { key: 1 }, oe = /* @__PURE__ */ T({
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: v }) {
298
- const r = v, p = E(!1), n = E([]), u = E(), t = E(""), e = M(
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
- r("update:modelValue", JSON.parse(JSON.stringify(o)));
309
+ d("update:modelValue", JSON.parse(JSON.stringify(o)));
309
310
  }
310
- }), { addEdges: s, removeEdges: g } = ve();
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 f = (o) => ({
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 = f(o.sourcePosition), N();
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 = f(o.targetPosition), N();
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
- }, x = async () => {
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 I = o?.findNode?.(b.id)?.dimensions;
348
- I?.width && I?.height && (i[b.id] = { width: I.width, height: I.height });
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 d = te(n.value, { dimensions: i }), w = /* @__PURE__ */ new Map();
351
- for (const b of d)
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 I = w.get(b.id);
356
- I && (b.position = I);
356
+ const x = w.get(b.id);
357
+ x && (b.position = x);
357
358
  }
358
- N(), await L(), await x();
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 d = n.value.length, w = `node-${d}`;
366
+ const r = n.value.length, w = `node-${r}`;
366
367
  if (n.value.push({
367
368
  id: w,
368
- label: "Node " + d,
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-${d + 1}`;
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 ${d + 1}`,
386
+ label: `EDGE ${r + 1}`,
386
387
  animated: !0
387
388
  });
388
389
  }
389
390
  N();
390
391
  }, V = (o, i) => {
391
- for (let d = 0; d < n.value.length; d++)
392
- if (n.value[d].id == i) {
393
- n.value[d].label = o;
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, d = o.source === o.target, w = {
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: d ? "selfloop" : "editable",
407
+ type: r ? "selfloop" : "editable",
407
408
  label: "New Edge",
408
409
  interactionWidth: 400,
409
410
  animated: !0
410
411
  };
411
- s([w]), await L(), N();
412
+ s([w]), await I(), N();
412
413
  }, se = async (o) => {
413
- g([o.edge.id]), await L(), N();
414
+ g([o.edge.id]), await I(), N();
414
415
  }, G = async (o) => {
415
- g([o]), await L(), N();
416
+ g([o]), await I(), N();
416
417
  }, N = () => {
417
- r("update:modelValue", JSON.parse(JSON.stringify(n.value)));
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] = (d) => p.value = !0),
424
- onMouseleave: i[3] || (i[3] = (d) => p.value = !1)
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", Le, [
427
- c("div", xe, [
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
- de(" " + F(t.value ? t.value : "none"), 1)
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: x
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(_(fe), {
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] = (d) => n.value = d),
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((d) => [
484
- O($e, A(d, {
485
- onChange: (w) => V(w, d.id)
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((d) => [
489
- O(ke, A(d, {
490
- onChange: (w) => V(w, d.id),
491
- onRemove: (w) => G(d.id)
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((d) => [
495
- O(Ie, A(d, {
496
- onChange: (w) => V(w, d.id),
497
- onRemove: (w) => G(d.id)
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, v) {
506
- const { states: r = [], actions: p = {} } = l, n = [], u = [];
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 < r.length; t++) {
539
- const e = r[t], a = {
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: v?.[e]?.position ?? { x: 200 * t, y: 100 },
543
- targetPosition: v?.[e]?.targetPosition ?? C.Left,
544
- sourcePosition: v?.[e]?.sourcePosition ?? C.Right
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, v) {
551
- const r = {}, p = {}, n = [];
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
- r[e.id] = a, n.push(a), e.position && (p[a] = {
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 = r[e.source] || e.source, m = r[e.target] || e.target, f = e.source === e.target;
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: f,
569
- ...f ? {} : { nextState: m }
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 = v?.actions?.[e];
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(v?.actions ?? {}))
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: { ...v, states: n, actions: t },
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__ */ re({
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 v = J(l, "modelValue"), r = J(l, "layout");
618
+ const f = J(l, "modelValue"), d = J(l, "layout");
618
619
  Z(() => {
619
- r.value === void 0 && console.warn("[StateEditor] v-model:layout is not bound. Node position changes will not be persisted.");
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 (!v.value) return [];
624
- const n = Me(v.value, r.value);
625
- return !r.value || Object.keys(r.value).length === 0 ? te(n) : n;
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, v.value);
629
- v.value = u, r.value !== void 0 && (r.value = t);
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
  };
@@ -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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"}
@@ -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
@@ -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;AAE5B;;;;GAIG;AACH,iBAAS,OAAO,CAAC,GAAG,EAAE,GAAG,QAGxB;AAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,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.30.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.30.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