@cyoda/workflow-react 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -37,6 +37,49 @@ var import_react24 = require("react");
37
37
  var import_workflow_core11 = require("@cyoda/workflow-core");
38
38
  var import_workflow_layout2 = require("@cyoda/workflow-layout");
39
39
 
40
+ // src/components/layoutPref.ts
41
+ var DENSITY_OPTIONS = [
42
+ { value: "websiteCompact", label: "Compact" },
43
+ { value: "opsAudit", label: "Comfortable" },
44
+ { value: "configuratorReadable", label: "Roomy" }
45
+ ];
46
+ var KNOWN_PRESETS = new Set(
47
+ DENSITY_OPTIONS.map((d) => d.value)
48
+ );
49
+ function defaultLayoutPref(opts) {
50
+ return {
51
+ orientation: opts?.orientation === "horizontal" ? "horizontal" : "vertical",
52
+ preset: opts?.preset && KNOWN_PRESETS.has(opts.preset) ? opts.preset : "configuratorReadable"
53
+ };
54
+ }
55
+ function prefKey(base) {
56
+ return base === null ? null : `${base}:pref`;
57
+ }
58
+ function loadLayoutPref(base, opts) {
59
+ const fallback = defaultLayoutPref(opts);
60
+ const key = prefKey(base);
61
+ if (key === null || typeof localStorage === "undefined") return fallback;
62
+ try {
63
+ const raw = localStorage.getItem(key);
64
+ if (!raw) return fallback;
65
+ const parsed = JSON.parse(raw);
66
+ return {
67
+ orientation: parsed.orientation === "horizontal" ? "horizontal" : "vertical",
68
+ preset: typeof parsed.preset === "string" && KNOWN_PRESETS.has(parsed.preset) ? parsed.preset : fallback.preset
69
+ };
70
+ } catch {
71
+ return fallback;
72
+ }
73
+ }
74
+ function saveLayoutPref(base, pref) {
75
+ const key = prefKey(base);
76
+ if (key === null || typeof localStorage === "undefined") return;
77
+ try {
78
+ localStorage.setItem(key, JSON.stringify(pref));
79
+ } catch {
80
+ }
81
+ }
82
+
40
83
  // src/i18n/context.ts
41
84
  var import_react = require("react");
42
85
 
@@ -63,8 +106,6 @@ var defaultMessages = {
63
106
  statesTitle: "States",
64
107
  stateInitial: "Initial \u2014 workflow entry point",
65
108
  stateDefault: "Regular state",
66
- stateProcessing: "Processing \u2014 automated work",
67
- stateManualReview: "Manual review \u2014 needs a person",
68
109
  stateTerminal: "Terminal \u2014 workflow ends here",
69
110
  stateError: "Red border \u2014 validation error",
70
111
  stateWarning: "Amber border \u2014 validation warning",
@@ -208,6 +249,8 @@ var defaultMessages = {
208
249
  noneManual: "No criterion. This manual transition is available whenever the entity is in this state.",
209
250
  noneAutomated: "No criterion. This automated transition will fire as soon as the entity reaches this state.",
210
251
  noneAutomatedWarning: "Automated transitions without criteria should usually be last in the transition order.",
252
+ workflowCaption: "Determines whether this workflow applies to an entity of its model \u2014 set one to disambiguate when several workflows target the same model.",
253
+ workflowNone: "No workflow criterion set.",
211
254
  cancel: "Cancel",
212
255
  applyModal: "Apply",
213
256
  revert: "Revert",
@@ -251,8 +294,6 @@ function summarize(patch) {
251
294
  return `Rename workflow "${patch.from}" \u2192 "${patch.to}"`;
252
295
  case "setInitialState":
253
296
  return `Set initial state to "${patch.stateCode}"`;
254
- case "setWorkflowCriterion":
255
- return patch.criterion ? `Set workflow criterion` : `Clear workflow criterion`;
256
297
  case "addState":
257
298
  return `Add state "${patch.stateCode}"`;
258
299
  case "renameState":
@@ -277,8 +318,10 @@ function summarize(patch) {
277
318
  return `Remove processor`;
278
319
  case "reorderProcessor":
279
320
  return `Reorder processor`;
280
- case "setCriterion":
281
- return patch.criterion ? `Set criterion` : `Clear criterion`;
321
+ case "setCriterion": {
322
+ const scope = patch.host.kind === "workflow" ? "workflow criterion" : "criterion";
323
+ return patch.criterion ? `Set ${scope}` : `Clear ${scope}`;
324
+ }
282
325
  case "setAnnotations":
283
326
  return patch.annotations ? `Set annotations` : `Clear annotations`;
284
327
  case "setImportMode":
@@ -511,20 +554,120 @@ var import_reactflow4 = require("reactflow");
511
554
  var import_style = require("reactflow/dist/style.css");
512
555
  var import_workflow_layout = require("@cyoda/workflow-layout");
513
556
 
557
+ // src/components/LayoutOptionsMenu.tsx
558
+ var import_jsx_runtime = require("react/jsx-runtime");
559
+ var ORIENTATION_OPTIONS = [
560
+ { value: "vertical", label: "Vertical" },
561
+ { value: "horizontal", label: "Horizontal" }
562
+ ];
563
+ function LayoutOptionsMenu({
564
+ orientation,
565
+ density,
566
+ onSetOrientation,
567
+ onSetDensity
568
+ }) {
569
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: panelStyle, "data-testid": "layout-options-menu", role: "group", "aria-label": "Auto-layout options", children: [
570
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: labelStyle, children: "Orientation" }),
571
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
572
+ Segmented,
573
+ {
574
+ options: ORIENTATION_OPTIONS,
575
+ value: orientation,
576
+ onChange: onSetOrientation,
577
+ testIdPrefix: "layout-orientation"
578
+ }
579
+ ),
580
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: labelStyle, children: "Density" }),
581
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
582
+ Segmented,
583
+ {
584
+ options: DENSITY_OPTIONS,
585
+ value: density,
586
+ onChange: onSetDensity,
587
+ testIdPrefix: "layout-density"
588
+ }
589
+ )
590
+ ] });
591
+ }
592
+ function Segmented({
593
+ options,
594
+ value,
595
+ onChange,
596
+ testIdPrefix
597
+ }) {
598
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: segmentedStyle, children: options.map((opt) => {
599
+ const active = opt.value === value;
600
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
601
+ "button",
602
+ {
603
+ type: "button",
604
+ onClick: () => onChange(opt.value),
605
+ "aria-pressed": active,
606
+ "data-testid": `${testIdPrefix}-${opt.value}`,
607
+ style: active ? segActiveStyle : segStyle,
608
+ children: opt.label
609
+ },
610
+ opt.value
611
+ );
612
+ }) });
613
+ }
614
+ var panelStyle = {
615
+ display: "flex",
616
+ flexDirection: "column",
617
+ gap: 6,
618
+ padding: 10,
619
+ width: 210,
620
+ background: "white",
621
+ border: "1px solid #D1D5DB",
622
+ borderRadius: 8,
623
+ boxShadow: "0 4px 16px rgba(15,23,42,0.14)"
624
+ };
625
+ var labelStyle = {
626
+ fontSize: 11,
627
+ fontWeight: 600,
628
+ letterSpacing: "0.04em",
629
+ color: "#64748B"
630
+ };
631
+ var segmentedStyle = {
632
+ display: "flex",
633
+ gap: 3,
634
+ padding: 3,
635
+ background: "#F1F5F9",
636
+ border: "1px solid #E2E8F0",
637
+ borderRadius: 7
638
+ };
639
+ var segStyle = {
640
+ flex: 1,
641
+ border: "none",
642
+ background: "transparent",
643
+ color: "#475569",
644
+ fontSize: 12,
645
+ fontWeight: 550,
646
+ padding: "5px 4px",
647
+ borderRadius: 5,
648
+ cursor: "pointer"
649
+ };
650
+ var segActiveStyle = {
651
+ ...segStyle,
652
+ background: "#2E63D6",
653
+ color: "white",
654
+ boxShadow: "0 1px 2px rgba(15,23,42,0.18)"
655
+ };
656
+
514
657
  // src/components/ArrowMarkers.tsx
515
658
  var import_theme = require("@cyoda/workflow-viewer/theme");
516
- var import_jsx_runtime = require("react/jsx-runtime");
659
+ var import_jsx_runtime2 = require("react/jsx-runtime");
517
660
  function ArrowMarkers() {
518
661
  const size = import_theme.geometry.edge.arrowheadSize;
519
662
  const colors2 = Array.from(new Set(Object.values(import_theme.workflowPalette.edge)));
520
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
663
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
521
664
  "svg",
522
665
  {
523
666
  width: 0,
524
667
  height: 0,
525
668
  style: { position: "absolute", pointerEvents: "none" },
526
669
  "aria-hidden": true,
527
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: colors2.map((color) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
670
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: colors2.map((color) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
528
671
  "marker",
529
672
  {
530
673
  id: arrowMarkerId(color),
@@ -534,7 +677,7 @@ function ArrowMarkers() {
534
677
  markerWidth: size,
535
678
  markerHeight: size,
536
679
  orient: "auto-start-reverse",
537
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
680
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
538
681
  "path",
539
682
  {
540
683
  d: `M 0 ${size / 2} L ${size * 2} ${size} L 0 ${size * 1.5} z`,
@@ -584,7 +727,7 @@ function computeHighlightSet(focusedId, nodes, edges) {
584
727
 
585
728
  // src/components/RfStateNode.tsx
586
729
  var import_theme2 = require("@cyoda/workflow-viewer/theme");
587
- var import_jsx_runtime2 = require("react/jsx-runtime");
730
+ var import_jsx_runtime3 = require("react/jsx-runtime");
588
731
  function StateRoleIcon({ label, color }) {
589
732
  const common = {
590
733
  width: 10,
@@ -597,24 +740,12 @@ function StateRoleIcon({ label, color }) {
597
740
  "aria-hidden": true
598
741
  };
599
742
  if (label === "INITIAL") {
600
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", { points: "2.5,1.5 8.5,5 2.5,8.5", fill: color, stroke: "none" }) });
743
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "2.5,1.5 8.5,5 2.5,8.5", fill: color, stroke: "none" }) });
601
744
  }
602
745
  if (label === "TERMINAL") {
603
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1.8", y: "1.8", width: "6.4", height: "6.4", rx: "1", fill: color, stroke: "none" }) });
604
- }
605
- if (label === "MANUAL REVIEW") {
606
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...common, viewBox: "0 0 10 10", children: [
607
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 2.2 L7 5 L5 7.8 L3 5 Z" }),
608
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "5", r: "0.8", fill: color, stroke: "none" })
609
- ] });
746
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "1.8", y: "1.8", width: "6.4", height: "6.4", rx: "1", fill: color, stroke: "none" }) });
610
747
  }
611
- if (label === "PROCESSING" || label === "PROCESSING STATE") {
612
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...common, viewBox: "0 0 10 10", children: [
613
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "5", r: "2.6" }),
614
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 1.4 V2.7 M5 7.3 V8.6 M1.4 5 H2.7 M7.3 5 H8.6" })
615
- ] });
616
- }
617
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "5", r: "2.2", fill: color, stroke: "none" }) });
748
+ return null;
618
749
  }
619
750
  function RfStateNodeImpl({ data, selected, id }) {
620
751
  const { node, hasError, hasWarning, size } = data;
@@ -628,7 +759,7 @@ function RfStateNodeImpl({ data, selected, id }) {
628
759
  const [showAnchors, setShowAnchors] = (0, import_react4.useState)(false);
629
760
  const borderColor = hasError ? "#DC2626" : hasWarning ? "#D97706" : selected ? import_theme2.workflowPalette.neutrals.slate900 : palette.border;
630
761
  const borderWidth = selected ? strokeWidth + 1 : strokeWidth;
631
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
762
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
632
763
  "div",
633
764
  {
634
765
  style: {
@@ -642,11 +773,11 @@ function RfStateNodeImpl({ data, selected, id }) {
642
773
  transition: "opacity 0.15s ease"
643
774
  },
644
775
  "data-testid": `rf-state-${node.stateCode}`,
645
- "aria-label": `${category} state: ${node.stateCode}`,
776
+ "aria-label": category ? `${category} state: ${node.stateCode}` : `state: ${node.stateCode}`,
646
777
  onMouseEnter: () => setShowAnchors(true),
647
778
  onMouseLeave: () => setShowAnchors(false),
648
779
  children: [
649
- ALL_ANCHORS.map(({ side, position, inset }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
780
+ ALL_ANCHORS.map(({ side, position, inset }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
650
781
  AnchorHandle,
651
782
  {
652
783
  side,
@@ -657,7 +788,7 @@ function RfStateNodeImpl({ data, selected, id }) {
657
788
  },
658
789
  side
659
790
  )),
660
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
791
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
661
792
  "div",
662
793
  {
663
794
  style: {
@@ -677,7 +808,7 @@ function RfStateNodeImpl({ data, selected, id }) {
677
808
  padding: "0 8px"
678
809
  },
679
810
  children: [
680
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
811
+ category && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
681
812
  "div",
682
813
  {
683
814
  style: {
@@ -694,12 +825,12 @@ function RfStateNodeImpl({ data, selected, id }) {
694
825
  },
695
826
  "data-testid": `rf-state-${node.stateCode}-category`,
696
827
  children: [
697
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StateRoleIcon, { label: category, color: palette.meta }),
828
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StateRoleIcon, { label: category, color: palette.meta }),
698
829
  category
699
830
  ]
700
831
  }
701
832
  ),
702
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
833
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
703
834
  "div",
704
835
  {
705
836
  style: {
@@ -798,8 +929,8 @@ function AnchorHandle({
798
929
  transition: "opacity 120ms ease",
799
930
  ...geo.dotOffset
800
931
  };
801
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
802
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
932
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
933
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
803
934
  import_reactflow.Handle,
804
935
  {
805
936
  id: side,
@@ -808,7 +939,7 @@ function AnchorHandle({
808
939
  style: handleStyle
809
940
  }
810
941
  ),
811
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
942
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
812
943
  import_reactflow.Handle,
813
944
  {
814
945
  id: side,
@@ -817,7 +948,7 @@ function AnchorHandle({
817
948
  style: handleStyle
818
949
  }
819
950
  ),
820
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: dotStyle })
951
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: dotStyle })
821
952
  ] });
822
953
  }
823
954
  function visibleHandleStyle(position, offset, isSplit, active) {
@@ -1212,10 +1343,11 @@ function midpoint(points) {
1212
1343
  }
1213
1344
 
1214
1345
  // src/components/TransitionTooltip.tsx
1346
+ var import_workflow_viewer = require("@cyoda/workflow-viewer");
1215
1347
  var import_theme3 = require("@cyoda/workflow-viewer/theme");
1216
- var import_jsx_runtime3 = require("react/jsx-runtime");
1348
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1217
1349
  function TransitionTooltip({ transition, x, y }) {
1218
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1350
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1219
1351
  "div",
1220
1352
  {
1221
1353
  style: {
@@ -1236,61 +1368,66 @@ function TransitionTooltip({ transition, x, y }) {
1236
1368
  pointerEvents: "none"
1237
1369
  },
1238
1370
  children: [
1239
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontWeight: 700, fontSize: 11, letterSpacing: "0.06em", marginBottom: 8, color: import_theme3.workflowPalette.neutrals.slate500, textTransform: "uppercase" }, children: transition.name }),
1240
- transition.criterion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { style: { marginBottom: transition.processors?.length ? 8 : 0 }, children: [
1241
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Label, { children: "Criterion" }),
1242
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CriterionView, { criterion: transition.criterion })
1371
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontWeight: 700, fontSize: 11, letterSpacing: "0.06em", marginBottom: 8, color: import_theme3.workflowPalette.neutrals.slate500, textTransform: "uppercase" }, children: transition.name }),
1372
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_workflow_viewer.AnnotationLines, { annotations: transition.annotations }),
1373
+ (transition.criterion || transition.criterionAnnotations) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { style: { marginBottom: transition.processors?.length ? 8 : 0 }, children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Label, { children: "Criterion" }),
1375
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_workflow_viewer.AnnotationLines, { annotations: transition.criterionAnnotations }),
1376
+ transition.criterion && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CriterionView, { criterion: transition.criterion })
1243
1377
  ] }),
1244
- !!transition.processors?.length && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { children: [
1245
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Label, { children: "Processors" }),
1246
- transition.processors.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ProcessorView, { processor: p }, i))
1378
+ !!transition.processors?.length && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Label, { children: "Processors" }),
1380
+ transition.processors.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ProcessorView, { processor: p }, i))
1247
1381
  ] }),
1248
- !transition.criterion && !transition.processors?.length && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: import_theme3.workflowPalette.neutrals.slate500, fontStyle: "italic" }, children: "No criterion or processors" })
1382
+ !transition.criterion && !transition.criterionAnnotations && !transition.processors?.length && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: import_theme3.workflowPalette.neutrals.slate500, fontStyle: "italic" }, children: "No criterion or processors" })
1249
1383
  ]
1250
1384
  }
1251
1385
  );
1252
1386
  }
1253
1387
  function Label({ children }) {
1254
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontWeight: 600, fontSize: 10, letterSpacing: "0.05em", color: import_theme3.workflowPalette.neutrals.slate500, textTransform: "uppercase", marginBottom: 4 }, children });
1388
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontWeight: 600, fontSize: 10, letterSpacing: "0.05em", color: import_theme3.workflowPalette.neutrals.slate500, textTransform: "uppercase", marginBottom: 4 }, children });
1255
1389
  }
1256
1390
  function CriterionView({ criterion, depth = 0 }) {
1257
1391
  const indent = depth * 12;
1258
1392
  const s = { paddingLeft: indent, marginBottom: 3 };
1259
- if (criterion.type === "simple") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1260
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "blue", children: criterion.operation }),
1261
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath }),
1262
- criterion.value !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { marginLeft: 4, color: import_theme3.workflowPalette.neutrals.slate500 }, children: [
1393
+ if (criterion.type === "simple") return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1394
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "blue", children: criterion.operation }),
1395
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath }),
1396
+ criterion.value !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { marginLeft: 4, color: import_theme3.workflowPalette.neutrals.slate500 }, children: [
1263
1397
  "= ",
1264
1398
  JSON.stringify(criterion.value)
1265
1399
  ] })
1266
1400
  ] });
1267
- if (criterion.type === "lifecycle") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s, children: [
1268
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "purple", children: criterion.field }),
1269
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1270
- criterion.value !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { marginLeft: 4, color: import_theme3.workflowPalette.neutrals.slate500 }, children: JSON.stringify(criterion.value) })
1401
+ if (criterion.type === "lifecycle") return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s, children: [
1402
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "purple", children: criterion.field }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1404
+ criterion.value !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { marginLeft: 4, color: import_theme3.workflowPalette.neutrals.slate500 }, children: JSON.stringify(criterion.value) })
1271
1405
  ] });
1272
- if (criterion.type === "function") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s, children: [
1273
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "green", children: "fn" }),
1274
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.function.name }),
1275
- criterion.function.criterion && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CriterionView, { criterion: criterion.function.criterion, depth: depth + 1 })
1406
+ if (criterion.type === "function") return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s, children: [
1407
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "green", children: "fn" }),
1408
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.function.name }),
1409
+ criterion.function.criterion && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CriterionView, { criterion: criterion.function.criterion, depth: depth + 1 })
1276
1410
  ] });
1277
- if (criterion.type === "array") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1278
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "orange", children: "array" }),
1279
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1280
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath })
1411
+ if (criterion.type === "array") return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1412
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "orange", children: "array" }),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1414
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath })
1281
1415
  ] });
1282
- if (criterion.type === "group") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s, children: [
1283
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "slate", children: criterion.operator }),
1284
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: 3 }, children: criterion.conditions.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CriterionView, { criterion: c, depth: depth + 1 }, i)) })
1416
+ if (criterion.type === "group") return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: s, children: [
1417
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "slate", children: criterion.operator }),
1418
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: 3 }, children: criterion.conditions.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CriterionView, { criterion: c, depth: depth + 1 }, i)) })
1285
1419
  ] });
1286
1420
  return null;
1287
1421
  }
1288
1422
  function ProcessorView({ processor }) {
1289
1423
  const mode = processor.executionMode ?? "ASYNC_NEW_TX";
1290
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: 4, display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1291
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { style: { fontSize: 11, fontWeight: 600 }, children: processor.name }),
1292
- mode !== "ASYNC_NEW_TX" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "blue", children: mode.replace(/_/g, " ") }),
1293
- processor.config?.calculationNodesTags && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chip, { color: "slate", children: processor.config.calculationNodesTags })
1424
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginBottom: 4 }, children: [
1425
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1426
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { style: { fontSize: 11, fontWeight: 600 }, children: processor.name }),
1427
+ mode !== "ASYNC_NEW_TX" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "blue", children: mode.replace(/_/g, " ") }),
1428
+ processor.config?.calculationNodesTags && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chip, { color: "slate", children: processor.config.calculationNodesTags })
1429
+ ] }),
1430
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_workflow_viewer.AnnotationLines, { annotations: processor.annotations })
1294
1431
  ] });
1295
1432
  }
1296
1433
  function Chip({ children, color, style }) {
@@ -1302,11 +1439,11 @@ function Chip({ children, color, style }) {
1302
1439
  slate: { bg: "#F1F5F9", text: "#475569" }
1303
1440
  };
1304
1441
  const { bg, text } = palette[color] ?? palette["slate"];
1305
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { background: bg, color: text, borderRadius: 3, padding: "1px 5px", fontSize: 10, fontWeight: 600, letterSpacing: "0.03em", ...style }, children });
1442
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { background: bg, color: text, borderRadius: 3, padding: "1px 5px", fontSize: 10, fontWeight: 600, letterSpacing: "0.03em", ...style }, children });
1306
1443
  }
1307
1444
 
1308
1445
  // src/components/RfTransitionEdge.tsx
1309
- var import_jsx_runtime4 = require("react/jsx-runtime");
1446
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1310
1447
  function RfTransitionEdgeImpl(props) {
1311
1448
  const {
1312
1449
  id,
@@ -1355,8 +1492,8 @@ function RfTransitionEdgeImpl(props) {
1355
1492
  manual: edge.manual,
1356
1493
  disabled: edge.disabled
1357
1494
  });
1358
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1359
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1495
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1496
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1360
1497
  import_reactflow3.BaseEdge,
1361
1498
  {
1362
1499
  id,
@@ -1371,7 +1508,7 @@ function RfTransitionEdgeImpl(props) {
1371
1508
  markerEnd: `url(#${arrowMarkerId(color)})`
1372
1509
  }
1373
1510
  ),
1374
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_reactflow3.EdgeLabelRenderer, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1511
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_reactflow3.EdgeLabelRenderer, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1375
1512
  "div",
1376
1513
  {
1377
1514
  style: {
@@ -1454,7 +1591,7 @@ function RfTransitionEdgeImpl(props) {
1454
1591
  }
1455
1592
  } : void 0,
1456
1593
  children: [
1457
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1594
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1458
1595
  "div",
1459
1596
  {
1460
1597
  style: {
@@ -1467,9 +1604,9 @@ function RfTransitionEdgeImpl(props) {
1467
1604
  children: edge.summary.display
1468
1605
  }
1469
1606
  ),
1470
- badges.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", gap: 3, flexWrap: "wrap", justifyContent: "center" }, children: badges.map((b, i) => {
1607
+ badges.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", gap: 3, flexWrap: "wrap", justifyContent: "center" }, children: badges.map((b, i) => {
1471
1608
  const slot = b.key === "manual" ? import_theme4.workflowPalette.badge.manual : b.key === "processor" || b.key === "execution" ? import_theme4.workflowPalette.badge.processor : b.key === "criterion" ? import_theme4.workflowPalette.badge.criterion : import_theme4.workflowPalette.badge.disabled;
1472
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1609
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1473
1610
  "span",
1474
1611
  {
1475
1612
  style: {
@@ -1491,7 +1628,7 @@ function RfTransitionEdgeImpl(props) {
1491
1628
  }
1492
1629
  ) }),
1493
1630
  tooltipPos && data.transition && (0, import_react_dom.createPortal)(
1494
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TransitionTooltip, { transition: data.transition, x: tooltipPos.x, y: tooltipPos.y }),
1631
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(TransitionTooltip, { transition: data.transition, x: tooltipPos.x, y: tooltipPos.y }),
1495
1632
  document.body
1496
1633
  )
1497
1634
  ] });
@@ -1531,7 +1668,7 @@ function findNonOverlappingCenter(desiredCenter, size, obstacles, options = {})
1531
1668
 
1532
1669
  // src/components/Canvas.tsx
1533
1670
  var import_theme5 = require("@cyoda/workflow-viewer/theme");
1534
- var import_jsx_runtime5 = require("react/jsx-runtime");
1671
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1535
1672
  var nodeTypes = { stateNode: RfStateNode };
1536
1673
  var edgeTypes = { transition: RfTransitionEdge };
1537
1674
  function toRfNodes(graph, layout, activeWorkflow, issuesByNode, selection) {
@@ -2400,6 +2537,7 @@ function CanvasInner({
2400
2537
  issues,
2401
2538
  activeWorkflow,
2402
2539
  selection,
2540
+ onToggleWorkflowSettings,
2403
2541
  layoutOptions,
2404
2542
  savedViewport,
2405
2543
  onSelectionChange,
@@ -2411,6 +2549,8 @@ function CanvasInner({
2411
2549
  onNodeDragStop,
2412
2550
  onPaneDoubleClick,
2413
2551
  newStatePositionRef,
2552
+ onSetLayoutOrientation,
2553
+ onSetLayoutDensity,
2414
2554
  layoutKey = 0,
2415
2555
  readOnly,
2416
2556
  showMinimap = true,
@@ -2429,6 +2569,7 @@ function CanvasInner({
2429
2569
  onTransitionLabelDragEnd
2430
2570
  }) {
2431
2571
  const [layout, setLayout] = (0, import_react6.useState)(null);
2572
+ const [layoutMenuOpen, setLayoutMenuOpen] = (0, import_react6.useState)(false);
2432
2573
  const [nodes, setNodes] = (0, import_react6.useState)([]);
2433
2574
  const [hoveredId, setHoveredId] = (0, import_react6.useState)(null);
2434
2575
  const previousBasePositionsRef = (0, import_react6.useRef)(null);
@@ -2605,6 +2746,7 @@ function CanvasInner({
2605
2746
  const onEdgeMouseEnter = (0, import_react6.useCallback)((_, edge) => setHoveredId(edge.id), []);
2606
2747
  const onEdgeMouseLeave = (0, import_react6.useCallback)(() => setHoveredId(null), []);
2607
2748
  const onNodeClick = (_, node) => {
2749
+ if (isReconnectingRef.current) return;
2608
2750
  const data = node.data;
2609
2751
  onSelectionChange({
2610
2752
  kind: "state",
@@ -2681,7 +2823,7 @@ function CanvasInner({
2681
2823
  newStatePositionRef.current = null;
2682
2824
  };
2683
2825
  }, [newStatePositionRef, computeNewStatePosition]);
2684
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HoverContext.Provider, { value: { highlightSet }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2826
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HoverContext.Provider, { value: { highlightSet }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2685
2827
  "div",
2686
2828
  {
2687
2829
  ref: wrapperRef,
@@ -2689,8 +2831,8 @@ function CanvasInner({
2689
2831
  "data-testid": "workflow-canvas",
2690
2832
  onDoubleClick: readOnly ? void 0 : handleCanvasDoubleClick,
2691
2833
  children: [
2692
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArrowMarkers, {}),
2693
- showControls && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2834
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArrowMarkers, {}),
2835
+ showControls && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2694
2836
  "div",
2695
2837
  {
2696
2838
  className: "nodrag nopan",
@@ -2708,12 +2850,12 @@ function CanvasInner({
2708
2850
  overflow: "hidden"
2709
2851
  },
2710
2852
  children: [
2711
- !readOnly && onUndo && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2712
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onUndo, disabled: !canUndo, title: "Undo (Ctrl+Z)", testId: "canvas-undo", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UndoIcon, {}) }),
2713
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onRedo, disabled: !canRedo, title: "Redo (Ctrl+Shift+Z)", testId: "canvas-redo", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RedoIcon, {}) }),
2714
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } })
2853
+ !readOnly && onUndo && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2854
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CtrlBtn, { onClick: onUndo, disabled: !canUndo, title: "Undo (Ctrl+Z)", testId: "canvas-undo", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(UndoIcon, {}) }),
2855
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CtrlBtn, { onClick: onRedo, disabled: !canRedo, title: "Redo (Ctrl+Shift+Z)", testId: "canvas-redo", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RedoIcon, {}) }),
2856
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: 1, background: "#E2E8F0" } })
2715
2857
  ] }),
2716
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2858
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2717
2859
  CtrlBtn,
2718
2860
  {
2719
2861
  onClick: () => {
@@ -2723,32 +2865,60 @@ function CanvasInner({
2723
2865
  });
2724
2866
  },
2725
2867
  title: "Fit view",
2726
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FitViewIcon, {})
2868
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FitViewIcon, {})
2727
2869
  }
2728
2870
  ),
2729
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onToggleFullscreen, title: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExitFullscreenIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EnterFullscreenIcon, {}) }),
2730
- !readOnly && onAutoLayout && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2731
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2732
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onAutoLayout, title: "Auto-arrange (L)", testId: "canvas-auto-layout", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AutoArrangeIcon, {}) })
2871
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CtrlBtn, { onClick: onToggleFullscreen, title: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ExitFullscreenIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EnterFullscreenIcon, {}) }),
2872
+ !readOnly && onAutoLayout && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2873
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2874
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CtrlBtn, { onClick: onAutoLayout, title: "Auto-arrange (L)", testId: "canvas-auto-layout", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AutoArrangeIcon, {}) }),
2875
+ onSetLayoutOrientation && onSetLayoutDensity && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2876
+ CtrlBtn,
2877
+ {
2878
+ onClick: () => setLayoutMenuOpen((v) => !v),
2879
+ title: "Layout options",
2880
+ testId: "canvas-layout-options",
2881
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LayoutOptionsIcon, {})
2882
+ }
2883
+ )
2733
2884
  ] }),
2734
- onHelp && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2735
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2736
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HelpIcon, {}) })
2885
+ onHelp && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2886
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2887
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HelpIcon, {}) })
2737
2888
  ] }),
2738
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2739
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2889
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2890
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2740
2891
  CtrlBtn,
2741
2892
  {
2742
- onClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2893
+ onClick: onToggleWorkflowSettings ?? (() => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null)),
2743
2894
  title: "Workflow settings",
2744
2895
  testId: "canvas-workflow-settings",
2745
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkflowSettingsIcon, {})
2896
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(WorkflowSettingsIcon, {})
2746
2897
  }
2747
2898
  )
2748
2899
  ]
2749
2900
  }
2750
2901
  ),
2751
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2902
+ layoutMenuOpen && onSetLayoutOrientation && onSetLayoutDensity && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2903
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2904
+ "div",
2905
+ {
2906
+ onClick: () => setLayoutMenuOpen(false),
2907
+ style: { position: "absolute", inset: 0, zIndex: 6 },
2908
+ "data-testid": "layout-options-backdrop"
2909
+ }
2910
+ ),
2911
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "nodrag nopan", style: { position: "absolute", bottom: 16, left: 64, zIndex: 7 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2912
+ LayoutOptionsMenu,
2913
+ {
2914
+ orientation,
2915
+ density: preset,
2916
+ onSetOrientation: onSetLayoutOrientation,
2917
+ onSetDensity: onSetLayoutDensity
2918
+ }
2919
+ ) })
2920
+ ] }),
2921
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2752
2922
  import_reactflow4.ReactFlow,
2753
2923
  {
2754
2924
  nodes,
@@ -2758,14 +2928,19 @@ function CanvasInner({
2758
2928
  onNodesChange: readOnly ? void 0 : handleNodesChange,
2759
2929
  onNodeClick,
2760
2930
  onEdgeClick,
2761
- onPaneClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2931
+ onPaneClick: () => {
2932
+ if (isReconnectingRef.current) return;
2933
+ onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null);
2934
+ },
2762
2935
  onConnect: readOnly ? void 0 : onConnect,
2763
2936
  onReconnect: readOnly ? void 0 : onReconnect,
2764
2937
  onReconnectStart: readOnly ? void 0 : () => {
2765
2938
  isReconnectingRef.current = true;
2766
2939
  },
2767
2940
  onReconnectEnd: readOnly ? void 0 : () => {
2768
- isReconnectingRef.current = false;
2941
+ setTimeout(() => {
2942
+ isReconnectingRef.current = false;
2943
+ }, 0);
2769
2944
  },
2770
2945
  onNodesDelete: readOnly ? void 0 : onNodesDelete,
2771
2946
  onEdgesDelete: readOnly ? void 0 : onEdgesDelete,
@@ -2791,8 +2966,8 @@ function CanvasInner({
2791
2966
  if (layout) onViewportChange?.(viewport);
2792
2967
  },
2793
2968
  children: [
2794
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_reactflow4.Background, {}),
2795
- showMinimap && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_reactflow4.MiniMap, { zoomable: true, pannable: true })
2969
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_reactflow4.Background, {}),
2970
+ showMinimap && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_reactflow4.MiniMap, { zoomable: true, pannable: true })
2796
2971
  ]
2797
2972
  }
2798
2973
  )
@@ -2807,7 +2982,7 @@ function CtrlBtn({
2807
2982
  testId,
2808
2983
  children
2809
2984
  }) {
2810
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2985
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2811
2986
  "button",
2812
2987
  {
2813
2988
  type: "button",
@@ -2832,50 +3007,58 @@ function CtrlBtn({
2832
3007
  );
2833
3008
  }
2834
3009
  function FitViewIcon() {
2835
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M3 7V4h3M18 4h3v3M21 17v3h-3M6 20H3v-3" }) });
3010
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M3 7V4h3M18 4h3v3M21 17v3h-3M6 20H3v-3" }) });
2836
3011
  }
2837
3012
  function UndoIcon() {
2838
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" }) });
3013
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" }) });
2839
3014
  }
2840
3015
  function RedoIcon() {
2841
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M15 15l6-6m0 0-6-6m6 6H9a6 6 0 0 0 0 12h3" }) });
3016
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M15 15l6-6m0 0-6-6m6 6H9a6 6 0 0 0 0 12h3" }) });
2842
3017
  }
2843
3018
  function EnterFullscreenIcon() {
2844
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M16 21h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) });
3019
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M16 21h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) });
2845
3020
  }
2846
3021
  function ExitFullscreenIcon() {
2847
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3" }) });
3022
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3" }) });
2848
3023
  }
2849
3024
  function AutoArrangeIcon() {
2850
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 22 20", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
2851
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "6", y: "0", width: "10", height: "5", rx: "1.5" }),
2852
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "11", y1: "5", x2: "11", y2: "9" }),
2853
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "9", x2: "18", y2: "9" }),
2854
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "9", x2: "4", y2: "12" }),
2855
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "18", y1: "9", x2: "18", y2: "12" }),
2856
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "0", y: "12", width: "8", height: "5", rx: "1.5" }),
2857
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "14", y: "12", width: "8", height: "5", rx: "1.5" })
3025
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 22 20", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3026
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "6", y: "0", width: "10", height: "5", rx: "1.5" }),
3027
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "11", y1: "5", x2: "11", y2: "9" }),
3028
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4", y1: "9", x2: "18", y2: "9" }),
3029
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4", y1: "9", x2: "4", y2: "12" }),
3030
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "18", y1: "9", x2: "18", y2: "12" }),
3031
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "0", y: "12", width: "8", height: "5", rx: "1.5" }),
3032
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "12", width: "8", height: "5", rx: "1.5" })
2858
3033
  ] });
2859
3034
  }
2860
3035
  function HelpIcon() {
2861
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2862
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
2863
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
2864
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
3036
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3037
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
3038
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
3039
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
3040
+ ] });
3041
+ }
3042
+ function LayoutOptionsIcon() {
3043
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 22 22", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
3044
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "7", x2: "19", y2: "7" }),
3045
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "15", x2: "19", y2: "15" }),
3046
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "8", cy: "7", r: "2.4", fill: "white" }),
3047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "14", cy: "15", r: "2.4", fill: "white" })
2865
3048
  ] });
2866
3049
  }
2867
3050
  function WorkflowSettingsIcon() {
2868
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2869
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "6", x2: "20", y2: "6" }),
2870
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "12", x2: "20", y2: "12" }),
2871
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "18", x2: "20", y2: "18" }),
2872
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "9", cy: "6", r: "2", fill: "white" }),
2873
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "15", cy: "12", r: "2", fill: "white" }),
2874
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "8", cy: "18", r: "2", fill: "white" })
3051
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3052
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4", y1: "6", x2: "20", y2: "6" }),
3053
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4", y1: "12", x2: "20", y2: "12" }),
3054
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4", y1: "18", x2: "20", y2: "18" }),
3055
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "9", cy: "6", r: "2", fill: "white" }),
3056
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "15", cy: "12", r: "2", fill: "white" }),
3057
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "8", cy: "18", r: "2", fill: "white" })
2875
3058
  ] });
2876
3059
  }
2877
3060
  function Canvas(props) {
2878
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_reactflow4.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CanvasInner, { ...props }) });
3061
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_reactflow4.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CanvasInner, { ...props }) });
2879
3062
  }
2880
3063
 
2881
3064
  // src/components/resolveConnection.ts
@@ -3054,7 +3237,7 @@ function resolveSelection(doc, selection) {
3054
3237
 
3055
3238
  // src/inspector/fields.tsx
3056
3239
  var import_react7 = require("react");
3057
- var import_jsx_runtime6 = require("react/jsx-runtime");
3240
+ var import_jsx_runtime7 = require("react/jsx-runtime");
3058
3241
  function TextField({
3059
3242
  label,
3060
3243
  value,
@@ -3072,9 +3255,9 @@ function TextField({
3072
3255
  syncedKeyRef.current = syncKey;
3073
3256
  setDraft(value);
3074
3257
  }
3075
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: rowStyle, children: [
3076
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: labelStyle, children: label }),
3077
- multiline ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3258
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { style: rowStyle, children: [
3259
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: labelStyle2, children: label }),
3260
+ multiline ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3078
3261
  "textarea",
3079
3262
  {
3080
3263
  value: draft,
@@ -3088,7 +3271,7 @@ function TextField({
3088
3271
  },
3089
3272
  style: { ...inputStyle, resize: "vertical", lineHeight: 1.5 }
3090
3273
  }
3091
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3274
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3092
3275
  "input",
3093
3276
  {
3094
3277
  type: "text",
@@ -3115,8 +3298,8 @@ function CheckboxField({
3115
3298
  disabled,
3116
3299
  testId
3117
3300
  }) {
3118
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { ...rowStyle, flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3301
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { style: { ...rowStyle, flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3302
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3120
3303
  "input",
3121
3304
  {
3122
3305
  type: "checkbox",
@@ -3126,7 +3309,7 @@ function CheckboxField({
3126
3309
  "data-testid": testId
3127
3310
  }
3128
3311
  ),
3129
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { ...labelStyle, marginBottom: 0 }, children: label })
3312
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { ...labelStyle2, marginBottom: 0 }, children: label })
3130
3313
  ] });
3131
3314
  }
3132
3315
  function SelectField({
@@ -3137,9 +3320,9 @@ function SelectField({
3137
3320
  disabled,
3138
3321
  testId
3139
3322
  }) {
3140
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: rowStyle, children: [
3141
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: labelStyle, children: label }),
3142
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3323
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { style: rowStyle, children: [
3324
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: labelStyle2, children: label }),
3325
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3143
3326
  CustomSelectInput,
3144
3327
  {
3145
3328
  value,
@@ -3217,8 +3400,8 @@ function CustomSelectInput({
3217
3400
  setHighlightedIndex((i) => Math.max(i - 1, 0));
3218
3401
  }
3219
3402
  };
3220
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: containerRef, style: { position: "relative" }, children: [
3221
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3403
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: containerRef, style: { position: "relative" }, children: [
3404
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3222
3405
  "select",
3223
3406
  {
3224
3407
  value,
@@ -3229,12 +3412,12 @@ function CustomSelectInput({
3229
3412
  "aria-hidden": "true",
3230
3413
  tabIndex: -1,
3231
3414
  children: [
3232
- disabledOption && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: disabledOption.value, disabled: true, children: disabledOption.label }),
3233
- groups ? groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("optgroup", { label: g.groupLabel, children: g.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: o.value, children: o.label }, o.value)) }, g.groupLabel)) : flatOptions.map((o) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: o.value, children: o.label }, o.value))
3415
+ disabledOption && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: disabledOption.value, disabled: true, children: disabledOption.label }),
3416
+ groups ? groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("optgroup", { label: g.groupLabel, children: g.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: o.value, children: o.label }, o.value)) }, g.groupLabel)) : flatOptions.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: o.value, children: o.label }, o.value))
3234
3417
  ]
3235
3418
  }
3236
3419
  ),
3237
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3420
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3238
3421
  "div",
3239
3422
  {
3240
3423
  role: "combobox",
@@ -3251,7 +3434,7 @@ function CustomSelectInput({
3251
3434
  children: selectedLabel
3252
3435
  }
3253
3436
  ),
3254
- open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3437
+ open && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3255
3438
  "div",
3256
3439
  {
3257
3440
  role: "listbox",
@@ -3271,7 +3454,7 @@ function CustomSelectInput({
3271
3454
  overflowY: "auto"
3272
3455
  },
3273
3456
  children: renderItems.map(
3274
- (item, i) => item.kind === "header" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3457
+ (item, i) => item.kind === "header" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3275
3458
  "div",
3276
3459
  {
3277
3460
  style: {
@@ -3287,7 +3470,7 @@ function CustomSelectInput({
3287
3470
  children: item.label
3288
3471
  },
3289
3472
  `header-${item.label}`
3290
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3473
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3291
3474
  "div",
3292
3475
  {
3293
3476
  role: "option",
@@ -3316,8 +3499,8 @@ function CustomSelectInput({
3316
3499
  ] });
3317
3500
  }
3318
3501
  function FieldGroup({ title, children }) {
3319
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
3320
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
3502
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
3503
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
3321
3504
  children
3322
3505
  ] });
3323
3506
  }
@@ -3326,7 +3509,7 @@ var rowStyle = {
3326
3509
  flexDirection: "column",
3327
3510
  gap: 4
3328
3511
  };
3329
- var labelStyle = {
3512
+ var labelStyle2 = {
3330
3513
  fontSize: 12,
3331
3514
  color: colors.textSecondary,
3332
3515
  marginBottom: 2
@@ -3389,7 +3572,7 @@ function installMonacoCancellationFilter() {
3389
3572
  installMonacoCancellationFilter();
3390
3573
 
3391
3574
  // src/inspector/JsonMonacoField.tsx
3392
- var import_jsx_runtime7 = require("react/jsx-runtime");
3575
+ var import_jsx_runtime8 = require("react/jsx-runtime");
3393
3576
  function reformat(text) {
3394
3577
  try {
3395
3578
  return JSON.stringify(JSON.parse(text), null, 2);
@@ -3404,8 +3587,8 @@ function JsonMonacoField(props) {
3404
3587
  const next = reformat(props.buffer);
3405
3588
  if (next !== null && next !== props.buffer) props.onChange(next);
3406
3589
  };
3407
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
3408
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3590
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
3591
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3409
3592
  "button",
3410
3593
  {
3411
3594
  type: "button",
@@ -3416,7 +3599,7 @@ function JsonMonacoField(props) {
3416
3599
  children: messages.inspector.format
3417
3600
  }
3418
3601
  ) }),
3419
- monaco ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3602
+ monaco ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3420
3603
  "textarea",
3421
3604
  {
3422
3605
  value: props.buffer,
@@ -3499,7 +3682,7 @@ function MonacoPane({
3499
3682
  (0, import_react9.useEffect)(() => {
3500
3683
  editorRef.current?.updateOptions?.({ readOnly: disabled });
3501
3684
  }, [disabled]);
3502
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3685
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3503
3686
  "div",
3504
3687
  {
3505
3688
  ref: containerRef,
@@ -3541,14 +3724,14 @@ function parseAnnotationsJson(text) {
3541
3724
  }
3542
3725
 
3543
3726
  // src/inspector/AnnotationsField.tsx
3544
- var import_jsx_runtime8 = require("react/jsx-runtime");
3727
+ var import_jsx_runtime9 = require("react/jsx-runtime");
3545
3728
  var pretty = (v) => JSON.stringify(v, null, 2);
3546
3729
  function AnnotationsField(props) {
3547
3730
  const messages = useMessages();
3548
3731
  if (props.value === void 0) {
3549
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: sectionStyle, children: [
3550
- props.showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SectionLabel, {}),
3551
- !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3732
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: sectionStyle, children: [
3733
+ props.showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SectionLabel, {}),
3734
+ !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3552
3735
  "button",
3553
3736
  {
3554
3737
  type: "button",
@@ -3560,7 +3743,7 @@ function AnnotationsField(props) {
3560
3743
  )
3561
3744
  ] });
3562
3745
  }
3563
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3746
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3564
3747
  }
3565
3748
  function AnnotationsEditor({
3566
3749
  value,
@@ -3600,9 +3783,9 @@ function AnnotationsEditor({
3600
3783
  setBuffer(pretty(value));
3601
3784
  setDocChanged(false);
3602
3785
  };
3603
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: sectionStyle, children: [
3604
- showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SectionLabel, {}),
3605
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3786
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: sectionStyle, children: [
3787
+ showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SectionLabel, {}),
3788
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3606
3789
  JsonMonacoField,
3607
3790
  {
3608
3791
  buffer,
@@ -3613,10 +3796,10 @@ function AnnotationsEditor({
3613
3796
  testId: "annotations-json-editor"
3614
3797
  }
3615
3798
  ),
3616
- result.error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", "data-testid": "annotations-error", style: errorStyle, children: result.error }),
3617
- docChanged && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", "data-testid": "annotations-doc-changed", style: warnStyle, children: messages.inspector.annotationsDocChanged }),
3618
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3619
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3799
+ result.error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "annotations-error", style: errorStyle, children: result.error }),
3800
+ docChanged && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", "data-testid": "annotations-doc-changed", style: warnStyle, children: messages.inspector.annotationsDocChanged }),
3801
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3802
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3620
3803
  "button",
3621
3804
  {
3622
3805
  type: "button",
@@ -3627,14 +3810,14 @@ function AnnotationsEditor({
3627
3810
  children: messages.inspector.annotationsApply
3628
3811
  }
3629
3812
  ),
3630
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtn, "data-testid": "inspector-annotations-revert", children: messages.inspector.annotationsRevert }),
3631
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: onRemove, style: dangerBtn, "data-testid": "inspector-annotations-remove", children: messages.inspector.annotationsRemove })
3813
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtn, "data-testid": "inspector-annotations-revert", children: messages.inspector.annotationsRevert }),
3814
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: onRemove, style: dangerBtn, "data-testid": "inspector-annotations-remove", children: messages.inspector.annotationsRemove })
3632
3815
  ] })
3633
3816
  ] });
3634
3817
  }
3635
3818
  function SectionLabel() {
3636
3819
  const messages = useMessages();
3637
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: messages.inspector.annotations });
3820
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: messages.inspector.annotations });
3638
3821
  }
3639
3822
  var sectionStyle = { display: "flex", flexDirection: "column", gap: 8 };
3640
3823
  var ghostBtn = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
@@ -3644,16 +3827,232 @@ var dangerBtn = { ...ghostBtn, background: colors.dangerBg, borderColor: colors.
3644
3827
  var errorStyle = { color: colors.danger, fontSize: 11 };
3645
3828
  var warnStyle = { color: colors.warning, fontSize: 11 };
3646
3829
 
3830
+ // src/inspector/CriterionField.tsx
3831
+ var import_react11 = require("react");
3832
+ var import_workflow_monaco = require("@cyoda/workflow-monaco");
3833
+
3834
+ // src/inspector/criterionJson.ts
3835
+ var import_workflow_core4 = require("@cyoda/workflow-core");
3836
+ function criterionModelUri(key) {
3837
+ return `cyoda://criterion/${key}.json`;
3838
+ }
3839
+ function zodMessage(error) {
3840
+ const first = error.issues[0];
3841
+ if (!first) return "Invalid criterion.";
3842
+ const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3843
+ return `${first.message}${path}`;
3844
+ }
3845
+ function parseCriterionJson(text) {
3846
+ let raw;
3847
+ try {
3848
+ raw = JSON.parse(text);
3849
+ } catch {
3850
+ return { criterion: null, error: "Invalid JSON." };
3851
+ }
3852
+ const res = import_workflow_core4.CriterionSchema.safeParse(raw);
3853
+ if (res.success) {
3854
+ const blocking = (0, import_workflow_core4.criterionBlockingError)(res.data);
3855
+ if (blocking) return { criterion: null, error: blocking };
3856
+ return { criterion: res.data, error: null };
3857
+ }
3858
+ let friendly = null;
3859
+ if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3860
+ try {
3861
+ friendly = (0, import_workflow_core4.criterionBlockingError)(raw);
3862
+ } catch {
3863
+ friendly = null;
3864
+ }
3865
+ }
3866
+ return { criterion: null, error: friendly ?? zodMessage(res.error) };
3867
+ }
3868
+
3869
+ // src/inspector/CriterionField.tsx
3870
+ var import_jsx_runtime10 = require("react/jsx-runtime");
3871
+ function defaultSimpleCriterion() {
3872
+ return { type: "simple", jsonPath: "", operation: "EQUALS" };
3873
+ }
3874
+ var pretty2 = (c) => JSON.stringify(c, null, 2);
3875
+ function CriterionField(props) {
3876
+ const m = useMessages().criterion;
3877
+ if (props.value === void 0) {
3878
+ const emptyText = props.emptyText ?? (props.manual ? m.noneManual : m.noneAutomated);
3879
+ const showWarning = props.emptyText === void 0 && !props.manual;
3880
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3881
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: summaryTextStyle, children: emptyText }),
3882
+ showWarning && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: warnStyle2, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3883
+ !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", style: primaryBtnStyle, "data-testid": "inspector-criterion-add", onClick: () => props.onCommit(defaultSimpleCriterion()), children: m.add })
3884
+ ] });
3885
+ }
3886
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CriterionEditor, { ...props, value: props.value }, props.modelKey);
3887
+ }
3888
+ function CriterionEditor({ value, disabled, modelKey, onCommit, onRemove }) {
3889
+ const messages = useMessages();
3890
+ const m = messages.criterion;
3891
+ const [expanded, setExpanded] = (0, import_react11.useState)(false);
3892
+ const [buffer, setBuffer] = (0, import_react11.useState)(() => pretty2(value));
3893
+ const [docChanged, setDocChanged] = (0, import_react11.useState)(false);
3894
+ const prevValueRef = (0, import_react11.useRef)(value);
3895
+ (0, import_react11.useEffect)(() => {
3896
+ if (sameJson(prevValueRef.current, value)) return;
3897
+ const parsed = parseCriterionJson(buffer).criterion;
3898
+ if (parsed !== null && sameJson(parsed, value)) {
3899
+ setDocChanged(false);
3900
+ } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3901
+ setBuffer(pretty2(value));
3902
+ setDocChanged(false);
3903
+ } else {
3904
+ setDocChanged(true);
3905
+ }
3906
+ prevValueRef.current = value;
3907
+ }, [value, buffer]);
3908
+ const result = parseCriterionJson(buffer);
3909
+ const dirty = result.criterion !== null && !sameJson(result.criterion, value);
3910
+ const applyEnabled = !disabled && result.criterion !== null && dirty;
3911
+ const canRevert = buffer !== pretty2(value);
3912
+ const apply = () => {
3913
+ if (!applyEnabled || result.criterion === null) return;
3914
+ onCommit(result.criterion);
3915
+ setDocChanged(false);
3916
+ setExpanded(false);
3917
+ };
3918
+ const revert = () => {
3919
+ setBuffer(pretty2(value));
3920
+ setDocChanged(false);
3921
+ };
3922
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3923
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3924
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: metaChipStyle, children: value.type }),
3925
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { flex: 1 } }),
3926
+ !disabled && !expanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", style: ghostBtnStyle, "data-testid": "inspector-criterion-edit", onClick: () => setExpanded(true), children: m.edit }),
3927
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", style: destructiveBtnStyle, "data-testid": "inspector-criterion-remove", onClick: onRemove, children: m.remove })
3928
+ ] }),
3929
+ !expanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CompactJson, { criterion: value }),
3930
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
3931
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3932
+ JsonMonacoField,
3933
+ {
3934
+ buffer,
3935
+ disabled,
3936
+ modelUri: criterionModelUri(modelKey),
3937
+ onChange: setBuffer,
3938
+ seed: buffer,
3939
+ registerSchema: import_workflow_monaco.registerCriterionSchema,
3940
+ testId: "criterion-json-editor"
3941
+ }
3942
+ ),
3943
+ result.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", "data-testid": "criterion-error", style: errorStyle2, children: result.error }),
3944
+ docChanged && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", "data-testid": "criterion-doc-changed", style: warnLineStyle, children: messages.inspector.annotationsDocChanged }),
3945
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3946
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: apply, disabled: !applyEnabled, style: applyEnabled ? primaryBtnStyle : { ...primaryBtnStyle, opacity: 0.5, cursor: "not-allowed" }, "data-testid": "inspector-criterion-apply", children: m.applyModal }),
3947
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtnStyle, "data-testid": "inspector-criterion-revert", children: m.revert }),
3948
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", onClick: () => setExpanded(false), style: ghostBtnStyle, "data-testid": "inspector-criterion-collapse", children: m.collapse })
3949
+ ] })
3950
+ ] })
3951
+ ] });
3952
+ }
3953
+ function CompactJson({ criterion }) {
3954
+ const text = JSON.stringify(criterion);
3955
+ const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
3956
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("code", { "data-testid": "criterion-compact-json", style: { display: "block", fontFamily: fonts.mono, fontSize: 11, color: colors.textSecondary, background: colors.surfaceMuted, padding: "6px 8px", borderRadius: radii.sm, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: display });
3957
+ }
3958
+ var cardStyle = { display: "flex", flexDirection: "column", gap: 8, padding: 10, border: `1px solid ${colors.border}`, borderRadius: radii.md, background: colors.surface };
3959
+ var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
3960
+ var warnStyle2 = { margin: 0, padding: "6px 8px", background: colors.warningBg, border: `1px solid ${colors.warningBorder}`, borderRadius: radii.sm, color: colors.warning, fontSize: 11 };
3961
+ var errorStyle2 = { color: colors.danger, fontSize: 11 };
3962
+ var warnLineStyle = { color: colors.warning, fontSize: 11 };
3963
+
3964
+ // src/inspector/CriterionForm.tsx
3965
+ var import_jsx_runtime11 = require("react/jsx-runtime");
3966
+ function criterionModelKey(host) {
3967
+ if (host.kind === "transition") return `transition-${host.transitionUuid}`;
3968
+ if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
3969
+ return `host-${host.workflow}`;
3970
+ }
3971
+ function criterionAnnotationsTarget(host) {
3972
+ if (host.kind === "workflow") return { kind: "workflowCriterion", workflow: host.workflow };
3973
+ if (host.kind === "transition") return { kind: "transitionCriterion", transitionUuid: host.transitionUuid };
3974
+ return void 0;
3975
+ }
3976
+ function CriterionSection({
3977
+ host,
3978
+ manual,
3979
+ criterion,
3980
+ criterionAnnotations,
3981
+ disabled,
3982
+ onDispatch,
3983
+ onSelectionChange: _onSelectionChange
3984
+ }) {
3985
+ const m = useMessages().criterion;
3986
+ const isWorkflow = host.kind === "workflow";
3987
+ const path = ["criterion"];
3988
+ const annotationsTarget = criterionAnnotationsTarget(host);
3989
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3990
+ isWorkflow && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3991
+ "p",
3992
+ {
3993
+ "data-testid": "workflow-criterion-caption",
3994
+ style: { margin: "0 0 6px", fontSize: 12, lineHeight: 1.4, color: colors.textSecondary },
3995
+ children: m.workflowCaption
3996
+ }
3997
+ ),
3998
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3999
+ CriterionField,
4000
+ {
4001
+ value: criterion,
4002
+ manual,
4003
+ disabled,
4004
+ modelKey: criterionModelKey(host),
4005
+ emptyText: isWorkflow ? m.workflowNone : void 0,
4006
+ onCommit: (next) => onDispatch({ op: "setCriterion", host, path, criterion: next }),
4007
+ onRemove: () => onDispatch({ op: "setCriterion", host, path, criterion: void 0 })
4008
+ }
4009
+ ),
4010
+ annotationsTarget && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
4011
+ "div",
4012
+ {
4013
+ "data-testid": "inspector-criterion-annotations",
4014
+ style: { display: "flex", flexDirection: "column", gap: 8, marginTop: 4 },
4015
+ children: [
4016
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4017
+ "span",
4018
+ {
4019
+ style: {
4020
+ fontSize: 11,
4021
+ fontWeight: 600,
4022
+ letterSpacing: "0.08em",
4023
+ textTransform: "uppercase",
4024
+ color: colors.textSecondary
4025
+ },
4026
+ children: "Criterion annotations"
4027
+ }
4028
+ ),
4029
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4030
+ AnnotationsField,
4031
+ {
4032
+ value: criterionAnnotations,
4033
+ disabled,
4034
+ showLabel: false,
4035
+ modelKey: `criterion-annotations-${criterionModelKey(host)}`,
4036
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: annotationsTarget, annotations }),
4037
+ onRemove: () => onDispatch({ op: "setAnnotations", target: annotationsTarget })
4038
+ }
4039
+ )
4040
+ ]
4041
+ }
4042
+ )
4043
+ ] });
4044
+ }
4045
+
3647
4046
  // src/inspector/WorkflowForm.tsx
3648
- var import_jsx_runtime9 = require("react/jsx-runtime");
4047
+ var import_jsx_runtime12 = require("react/jsx-runtime");
3649
4048
  function WorkflowForm({
3650
4049
  workflow,
3651
4050
  disabled,
3652
4051
  onDispatch
3653
4052
  }) {
3654
4053
  const messages = useMessages();
3655
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3656
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4054
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
4055
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3657
4056
  TextField,
3658
4057
  {
3659
4058
  label: messages.inspector.name,
@@ -3663,7 +4062,7 @@ function WorkflowForm({
3663
4062
  testId: "inspector-workflow-name"
3664
4063
  }
3665
4064
  ),
3666
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4065
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3667
4066
  TextField,
3668
4067
  {
3669
4068
  label: messages.inspector.version,
@@ -3678,7 +4077,7 @@ function WorkflowForm({
3678
4077
  testId: "inspector-workflow-version"
3679
4078
  }
3680
4079
  ),
3681
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4080
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3682
4081
  TextField,
3683
4082
  {
3684
4083
  label: messages.inspector.description,
@@ -3694,7 +4093,7 @@ function WorkflowForm({
3694
4093
  testId: "inspector-workflow-desc"
3695
4094
  }
3696
4095
  ),
3697
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4096
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3698
4097
  CheckboxField,
3699
4098
  {
3700
4099
  label: messages.inspector.active,
@@ -3708,7 +4107,7 @@ function WorkflowForm({
3708
4107
  testId: "inspector-workflow-active"
3709
4108
  }
3710
4109
  ),
3711
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4110
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3712
4111
  TextField,
3713
4112
  {
3714
4113
  label: messages.inspector.initialState,
@@ -3723,7 +4122,7 @@ function WorkflowForm({
3723
4122
  testId: "inspector-workflow-initial"
3724
4123
  }
3725
4124
  ),
3726
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4125
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3727
4126
  AnnotationsField,
3728
4127
  {
3729
4128
  value: workflow.annotations,
@@ -3732,14 +4131,24 @@ function WorkflowForm({
3732
4131
  onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name }, annotations }),
3733
4132
  onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name } })
3734
4133
  }
4134
+ ),
4135
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4136
+ CriterionSection,
4137
+ {
4138
+ host: { kind: "workflow", workflow: workflow.name },
4139
+ criterion: workflow.criterion,
4140
+ criterionAnnotations: workflow.criterionAnnotations,
4141
+ disabled,
4142
+ onDispatch
4143
+ }
3735
4144
  )
3736
4145
  ] });
3737
4146
  }
3738
4147
 
3739
4148
  // src/inspector/StateForm.tsx
3740
- var import_react11 = require("react");
3741
- var import_workflow_core4 = require("@cyoda/workflow-core");
3742
- var import_jsx_runtime10 = require("react/jsx-runtime");
4149
+ var import_react12 = require("react");
4150
+ var import_workflow_core5 = require("@cyoda/workflow-core");
4151
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3743
4152
  function StateForm({
3744
4153
  workflow,
3745
4154
  stateCode,
@@ -3750,7 +4159,7 @@ function StateForm({
3750
4159
  onRequestDelete
3751
4160
  }) {
3752
4161
  const messages = useMessages();
3753
- const [renameError, setRenameError] = (0, import_react11.useState)(null);
4162
+ const [renameError, setRenameError] = (0, import_react12.useState)(null);
3754
4163
  const outgoing = state.transitions.length;
3755
4164
  const incoming = Object.values(workflow.states).reduce(
3756
4165
  (n, s) => n + s.transitions.filter((t) => t.next === stateCode).length,
@@ -3763,7 +4172,7 @@ function StateForm({
3763
4172
  const handleRename = (next) => {
3764
4173
  if (next === stateCode) return;
3765
4174
  setRenameError(null);
3766
- if (!import_workflow_core4.NAME_REGEX.test(next)) {
4175
+ if (!import_workflow_core5.NAME_REGEX.test(next)) {
3767
4176
  setRenameError(`"${next}" is not a valid state name`);
3768
4177
  return;
3769
4178
  }
@@ -3773,8 +4182,8 @@ function StateForm({
3773
4182
  }
3774
4183
  onDispatch({ op: "renameState", workflow: workflow.name, from: stateCode, to: next });
3775
4184
  };
3776
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3777
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4185
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
4186
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3778
4187
  TextField,
3779
4188
  {
3780
4189
  label: messages.inspector.name,
@@ -3785,19 +4194,19 @@ function StateForm({
3785
4194
  testId: "inspector-state-name"
3786
4195
  }
3787
4196
  ),
3788
- renameError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
3789
- (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3790
- isInitial && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
3791
- isTerminal && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
3792
- isUnreachable && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
4197
+ renameError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4198
+ (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4199
+ isInitial && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
4200
+ isTerminal && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
4201
+ isUnreachable && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
3793
4202
  ] }),
3794
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
4203
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3795
4204
  outgoing,
3796
4205
  " outgoing \xB7 ",
3797
4206
  incoming,
3798
4207
  " incoming"
3799
4208
  ] }),
3800
- !isInitial && !disabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4209
+ !isInitial && !disabled && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3801
4210
  "button",
3802
4211
  {
3803
4212
  type: "button",
@@ -3807,7 +4216,7 @@ function StateForm({
3807
4216
  children: "Set as Initial State"
3808
4217
  }
3809
4218
  ),
3810
- issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4219
+ issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3811
4220
  "div",
3812
4221
  {
3813
4222
  role: "alert",
@@ -3823,7 +4232,7 @@ function StateForm({
3823
4232
  },
3824
4233
  `${issue.code}-${i}`
3825
4234
  )) }),
3826
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4235
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3827
4236
  AnnotationsField,
3828
4237
  {
3829
4238
  value: state.annotations,
@@ -3833,236 +4242,75 @@ function StateForm({
3833
4242
  onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode } })
3834
4243
  }
3835
4244
  ),
3836
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4245
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3837
4246
  "button",
3838
4247
  {
3839
4248
  type: "button",
3840
- onClick: onRequestDelete,
3841
- disabled,
3842
- "data-testid": "inspector-state-delete",
3843
- style: dangerBtn2,
3844
- children: "Delete state\u2026"
3845
- }
3846
- )
3847
- ] });
3848
- }
3849
- function StateBadge({ color, bg, label }) {
3850
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3851
- "span",
3852
- {
3853
- style: {
3854
- padding: "2px 8px",
3855
- background: bg,
3856
- color,
3857
- border: `1px solid ${color}`,
3858
- borderRadius: 999,
3859
- fontSize: 11,
3860
- fontWeight: 600
3861
- },
3862
- children: label
3863
- }
3864
- );
3865
- }
3866
- function reachableStates(wf) {
3867
- const visited = /* @__PURE__ */ new Set();
3868
- if (!(wf.initialState in wf.states)) return visited;
3869
- const queue = [wf.initialState];
3870
- visited.add(wf.initialState);
3871
- while (queue.length) {
3872
- const cur = queue.shift();
3873
- for (const t of wf.states[cur]?.transitions ?? []) {
3874
- if (!visited.has(t.next) && t.next in wf.states) {
3875
- visited.add(t.next);
3876
- queue.push(t.next);
3877
- }
3878
- }
3879
- }
3880
- return visited;
3881
- }
3882
- var ghostBtn2 = {
3883
- alignSelf: "flex-start",
3884
- padding: "5px 10px",
3885
- background: "white",
3886
- border: `1px solid ${colors.border}`,
3887
- borderRadius: radii.sm,
3888
- fontSize: 13,
3889
- cursor: "pointer"
3890
- };
3891
- var dangerBtn2 = {
3892
- alignSelf: "flex-start",
3893
- padding: "6px 10px",
3894
- background: colors.dangerBg,
3895
- border: `1px solid ${colors.dangerBorder}`,
3896
- color: colors.danger,
3897
- borderRadius: radii.sm,
3898
- fontSize: 13,
3899
- cursor: "pointer"
3900
- };
3901
-
3902
- // src/inspector/TransitionForm.tsx
3903
- var import_react15 = require("react");
3904
- var import_workflow_core7 = require("@cyoda/workflow-core");
3905
-
3906
- // src/inspector/CriterionField.tsx
3907
- var import_react12 = require("react");
3908
- var import_workflow_monaco = require("@cyoda/workflow-monaco");
3909
-
3910
- // src/inspector/criterionJson.ts
3911
- var import_workflow_core5 = require("@cyoda/workflow-core");
3912
- function criterionModelUri(key) {
3913
- return `cyoda://criterion/${key}.json`;
3914
- }
3915
- function zodMessage(error) {
3916
- const first = error.issues[0];
3917
- if (!first) return "Invalid criterion.";
3918
- const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3919
- return `${first.message}${path}`;
3920
- }
3921
- function parseCriterionJson(text) {
3922
- let raw;
3923
- try {
3924
- raw = JSON.parse(text);
3925
- } catch {
3926
- return { criterion: null, error: "Invalid JSON." };
3927
- }
3928
- const res = import_workflow_core5.CriterionSchema.safeParse(raw);
3929
- if (res.success) {
3930
- const blocking = (0, import_workflow_core5.criterionBlockingError)(res.data);
3931
- if (blocking) return { criterion: null, error: blocking };
3932
- return { criterion: res.data, error: null };
3933
- }
3934
- let friendly = null;
3935
- if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3936
- try {
3937
- friendly = (0, import_workflow_core5.criterionBlockingError)(raw);
3938
- } catch {
3939
- friendly = null;
3940
- }
3941
- }
3942
- return { criterion: null, error: friendly ?? zodMessage(res.error) };
3943
- }
3944
-
3945
- // src/inspector/CriterionField.tsx
3946
- var import_jsx_runtime11 = require("react/jsx-runtime");
3947
- function defaultSimpleCriterion() {
3948
- return { type: "simple", jsonPath: "", operation: "EQUALS" };
3949
- }
3950
- var pretty2 = (c) => JSON.stringify(c, null, 2);
3951
- function CriterionField(props) {
3952
- const m = useMessages().criterion;
3953
- if (props.value === void 0) {
3954
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3955
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: summaryTextStyle, children: props.manual ? m.noneManual : m.noneAutomated }),
3956
- !props.manual && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: warnStyle2, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3957
- !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: primaryBtnStyle, "data-testid": "inspector-criterion-add", onClick: () => props.onCommit(defaultSimpleCriterion()), children: m.add })
3958
- ] });
3959
- }
3960
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CriterionEditor, { ...props, value: props.value }, props.modelKey);
3961
- }
3962
- function CriterionEditor({ value, disabled, modelKey, onCommit, onRemove }) {
3963
- const messages = useMessages();
3964
- const m = messages.criterion;
3965
- const [expanded, setExpanded] = (0, import_react12.useState)(false);
3966
- const [buffer, setBuffer] = (0, import_react12.useState)(() => pretty2(value));
3967
- const [docChanged, setDocChanged] = (0, import_react12.useState)(false);
3968
- const prevValueRef = (0, import_react12.useRef)(value);
3969
- (0, import_react12.useEffect)(() => {
3970
- if (sameJson(prevValueRef.current, value)) return;
3971
- const parsed = parseCriterionJson(buffer).criterion;
3972
- if (parsed !== null && sameJson(parsed, value)) {
3973
- setDocChanged(false);
3974
- } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3975
- setBuffer(pretty2(value));
3976
- setDocChanged(false);
3977
- } else {
3978
- setDocChanged(true);
3979
- }
3980
- prevValueRef.current = value;
3981
- }, [value, buffer]);
3982
- const result = parseCriterionJson(buffer);
3983
- const dirty = result.criterion !== null && !sameJson(result.criterion, value);
3984
- const applyEnabled = !disabled && result.criterion !== null && dirty;
3985
- const canRevert = buffer !== pretty2(value);
3986
- const apply = () => {
3987
- if (!applyEnabled || result.criterion === null) return;
3988
- onCommit(result.criterion);
3989
- setDocChanged(false);
3990
- setExpanded(false);
3991
- };
3992
- const revert = () => {
3993
- setBuffer(pretty2(value));
3994
- setDocChanged(false);
3995
- };
3996
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3997
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3998
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: metaChipStyle, children: value.type }),
3999
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { flex: 1 } }),
4000
- !disabled && !expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: ghostBtnStyle, "data-testid": "inspector-criterion-edit", onClick: () => setExpanded(true), children: m.edit }),
4001
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: destructiveBtnStyle, "data-testid": "inspector-criterion-remove", onClick: onRemove, children: m.remove })
4002
- ] }),
4003
- !expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CompactJson, { criterion: value }),
4004
- expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
4005
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4006
- JsonMonacoField,
4007
- {
4008
- buffer,
4009
- disabled,
4010
- modelUri: criterionModelUri(modelKey),
4011
- onChange: setBuffer,
4012
- seed: buffer,
4013
- registerSchema: import_workflow_monaco.registerCriterionSchema,
4014
- testId: "criterion-json-editor"
4015
- }
4016
- ),
4017
- result.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", "data-testid": "criterion-error", style: errorStyle2, children: result.error }),
4018
- docChanged && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", "data-testid": "criterion-doc-changed", style: warnLineStyle, children: messages.inspector.annotationsDocChanged }),
4019
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4020
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: apply, disabled: !applyEnabled, style: applyEnabled ? primaryBtnStyle : { ...primaryBtnStyle, opacity: 0.5, cursor: "not-allowed" }, "data-testid": "inspector-criterion-apply", children: m.applyModal }),
4021
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtnStyle, "data-testid": "inspector-criterion-revert", children: m.revert }),
4022
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: () => setExpanded(false), style: ghostBtnStyle, "data-testid": "inspector-criterion-collapse", children: m.collapse })
4023
- ] })
4024
- ] })
4025
- ] });
4026
- }
4027
- function CompactJson({ criterion }) {
4028
- const text = JSON.stringify(criterion);
4029
- const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
4030
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { "data-testid": "criterion-compact-json", style: { display: "block", fontFamily: fonts.mono, fontSize: 11, color: colors.textSecondary, background: colors.surfaceMuted, padding: "6px 8px", borderRadius: radii.sm, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: display });
4031
- }
4032
- var cardStyle = { display: "flex", flexDirection: "column", gap: 8, padding: 10, border: `1px solid ${colors.border}`, borderRadius: radii.md, background: colors.surface };
4033
- var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
4034
- var warnStyle2 = { margin: 0, padding: "6px 8px", background: colors.warningBg, border: `1px solid ${colors.warningBorder}`, borderRadius: radii.sm, color: colors.warning, fontSize: 11 };
4035
- var errorStyle2 = { color: colors.danger, fontSize: 11 };
4036
- var warnLineStyle = { color: colors.warning, fontSize: 11 };
4037
-
4038
- // src/inspector/CriterionForm.tsx
4039
- var import_jsx_runtime12 = require("react/jsx-runtime");
4040
- function criterionModelKey(host) {
4041
- if (host.kind === "transition") return `transition-${host.transitionUuid}`;
4042
- if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
4043
- return `host-${host.workflow}`;
4249
+ onClick: onRequestDelete,
4250
+ disabled,
4251
+ "data-testid": "inspector-state-delete",
4252
+ style: dangerBtn2,
4253
+ children: "Delete state\u2026"
4254
+ }
4255
+ )
4256
+ ] });
4044
4257
  }
4045
- function CriterionSection({
4046
- host,
4047
- manual,
4048
- criterion,
4049
- disabled,
4050
- onDispatch,
4051
- onSelectionChange: _onSelectionChange
4052
- }) {
4053
- const path = ["criterion"];
4054
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4055
- CriterionField,
4258
+ function StateBadge({ color, bg, label }) {
4259
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4260
+ "span",
4056
4261
  {
4057
- value: criterion,
4058
- manual,
4059
- disabled,
4060
- modelKey: criterionModelKey(host),
4061
- onCommit: (next) => onDispatch({ op: "setCriterion", host, path, criterion: next }),
4062
- onRemove: () => onDispatch({ op: "setCriterion", host, path, criterion: void 0 })
4262
+ style: {
4263
+ padding: "2px 8px",
4264
+ background: bg,
4265
+ color,
4266
+ border: `1px solid ${color}`,
4267
+ borderRadius: 999,
4268
+ fontSize: 11,
4269
+ fontWeight: 600
4270
+ },
4271
+ children: label
4063
4272
  }
4064
4273
  );
4065
4274
  }
4275
+ function reachableStates(wf) {
4276
+ const visited = /* @__PURE__ */ new Set();
4277
+ if (!(wf.initialState in wf.states)) return visited;
4278
+ const queue = [wf.initialState];
4279
+ visited.add(wf.initialState);
4280
+ while (queue.length) {
4281
+ const cur = queue.shift();
4282
+ for (const t of wf.states[cur]?.transitions ?? []) {
4283
+ if (!visited.has(t.next) && t.next in wf.states) {
4284
+ visited.add(t.next);
4285
+ queue.push(t.next);
4286
+ }
4287
+ }
4288
+ }
4289
+ return visited;
4290
+ }
4291
+ var ghostBtn2 = {
4292
+ alignSelf: "flex-start",
4293
+ padding: "5px 10px",
4294
+ background: "white",
4295
+ border: `1px solid ${colors.border}`,
4296
+ borderRadius: radii.sm,
4297
+ fontSize: 13,
4298
+ cursor: "pointer"
4299
+ };
4300
+ var dangerBtn2 = {
4301
+ alignSelf: "flex-start",
4302
+ padding: "6px 10px",
4303
+ background: colors.dangerBg,
4304
+ border: `1px solid ${colors.dangerBorder}`,
4305
+ color: colors.danger,
4306
+ borderRadius: radii.sm,
4307
+ fontSize: 13,
4308
+ cursor: "pointer"
4309
+ };
4310
+
4311
+ // src/inspector/TransitionForm.tsx
4312
+ var import_react15 = require("react");
4313
+ var import_workflow_core7 = require("@cyoda/workflow-core");
4066
4314
 
4067
4315
  // src/inspector/ProcessorForm.tsx
4068
4316
  var import_react14 = require("react");
@@ -4070,7 +4318,7 @@ var import_workflow_core6 = require("@cyoda/workflow-core");
4070
4318
 
4071
4319
  // src/modals/DeleteStateModal.tsx
4072
4320
  var import_react13 = require("react");
4073
- var import_jsx_runtime13 = require("react/jsx-runtime");
4321
+ var import_jsx_runtime14 = require("react/jsx-runtime");
4074
4322
  function countAffected(doc, workflow, stateCode) {
4075
4323
  let outgoing = 0;
4076
4324
  let incoming = 0;
@@ -4096,20 +4344,20 @@ function DeleteStateModal({
4096
4344
  () => countAffected(doc, workflow, stateCode),
4097
4345
  [doc, workflow, stateCode]
4098
4346
  );
4099
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ModalFrame, { onCancel, children: [
4100
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
4101
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
4102
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
4103
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: stateCode }),
4104
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { color: colors.textSecondary }, children: [
4347
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(ModalFrame, { onCancel, children: [
4348
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
4349
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
4350
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
4351
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: stateCode }),
4352
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { color: colors.textSecondary }, children: [
4105
4353
  messages.confirmDelete.transitionsAffected,
4106
4354
  ": ",
4107
4355
  counts.outgoing + counts.incoming
4108
4356
  ] })
4109
4357
  ] }),
4110
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
4111
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
4112
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: onConfirm, style: dangerBtn3, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
4358
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
4359
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
4360
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onConfirm, style: dangerBtn3, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
4113
4361
  ] })
4114
4362
  ] });
4115
4363
  }
@@ -4133,7 +4381,7 @@ function ModalFrame({
4133
4381
  previousFocusRef.current?.focus?.();
4134
4382
  };
4135
4383
  }, []);
4136
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4384
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4137
4385
  "div",
4138
4386
  {
4139
4387
  onClick: onCancel,
@@ -4153,7 +4401,7 @@ function ModalFrame({
4153
4401
  zIndex: 1e3
4154
4402
  },
4155
4403
  "data-testid": "modal-backdrop",
4156
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4404
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4157
4405
  "div",
4158
4406
  {
4159
4407
  ref: frameRef,
@@ -4195,7 +4443,7 @@ var dangerBtn3 = {
4195
4443
  };
4196
4444
 
4197
4445
  // src/inspector/ProcessorForm.tsx
4198
- var import_jsx_runtime14 = require("react/jsx-runtime");
4446
+ var import_jsx_runtime15 = require("react/jsx-runtime");
4199
4447
  var EXECUTION_MODES = [
4200
4448
  "ASYNC_NEW_TX",
4201
4449
  "ASYNC_SAME_TX",
@@ -4227,7 +4475,8 @@ function toDraft(processor) {
4227
4475
  retryPolicy: externalized?.config?.retryPolicy ?? "",
4228
4476
  context: externalized?.config?.context ?? "",
4229
4477
  asyncResult: externalized?.config?.asyncResult ?? false,
4230
- crossoverToAsyncMs: externalized?.config?.crossoverToAsyncMs !== void 0 ? String(externalized.config.crossoverToAsyncMs) : ""
4478
+ crossoverToAsyncMs: externalized?.config?.crossoverToAsyncMs !== void 0 ? String(externalized.config.crossoverToAsyncMs) : "",
4479
+ annotations: externalized?.annotations
4231
4480
  };
4232
4481
  }
4233
4482
  function toProcessor(draft) {
@@ -4249,7 +4498,8 @@ function toProcessor(draft) {
4249
4498
  name: draft.name.trim(),
4250
4499
  executionMode: draft.executionMode,
4251
4500
  ...draft.executionMode === "COMMIT_BEFORE_DISPATCH" && draft.startNewTxOnDispatch ? { startNewTxOnDispatch: true } : {},
4252
- ...Object.keys(config).length > 0 ? { config } : {}
4501
+ ...Object.keys(config).length > 0 ? { config } : {},
4502
+ ...draft.annotations !== void 0 ? { annotations: draft.annotations } : {}
4253
4503
  };
4254
4504
  }
4255
4505
  function validateDraft(draft, existingNames, originalName) {
@@ -4301,13 +4551,13 @@ function ProcessorEditorModal({
4301
4551
  if (disabled || error) return;
4302
4552
  onApply(toProcessor(draft));
4303
4553
  };
4304
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: modalStyle, "data-testid": "processor-editor-modal", children: [
4305
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4306
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4307
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4554
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: modalStyle, "data-testid": "processor-editor-modal", children: [
4555
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4556
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4557
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4308
4558
  ] }),
4309
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: modalBodyStyle, children: [
4310
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4559
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: modalBodyStyle, children: [
4560
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4311
4561
  "input",
4312
4562
  {
4313
4563
  type: "text",
@@ -4317,17 +4567,42 @@ function ProcessorEditorModal({
4317
4567
  style: inputStyle2
4318
4568
  }
4319
4569
  ) }),
4320
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Execution mode", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4570
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Execution mode", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4321
4571
  CustomSelectInput,
4322
4572
  {
4323
4573
  value: draft.executionMode,
4324
4574
  options: EXECUTION_MODES.map((mode) => ({ value: mode, label: mode })),
4325
- onChange: (next) => setDraft((current) => ({ ...current, executionMode: next })),
4575
+ onChange: (next) => setDraft((current) => ({
4576
+ ...current,
4577
+ executionMode: next,
4578
+ // startNewTxOnDispatch is only valid for COMMIT_BEFORE_DISPATCH.
4579
+ startNewTxOnDispatch: next === "COMMIT_BEFORE_DISPATCH" ? current.startNewTxOnDispatch : false
4580
+ })),
4326
4581
  testId: "processor-execution-mode"
4327
4582
  }
4328
4583
  ) }),
4329
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: checkboxRowStyle, children: [
4330
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4584
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4585
+ "label",
4586
+ {
4587
+ style: draft.executionMode === "COMMIT_BEFORE_DISPATCH" ? checkboxRowStyle : { ...checkboxRowStyle, opacity: 0.5 },
4588
+ title: "Only for COMMIT_BEFORE_DISPATCH: open a fresh transaction context for the dispatched call.",
4589
+ children: [
4590
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4591
+ "input",
4592
+ {
4593
+ type: "checkbox",
4594
+ checked: draft.startNewTxOnDispatch,
4595
+ disabled: disabled || draft.executionMode !== "COMMIT_BEFORE_DISPATCH",
4596
+ onChange: (event) => setDraft((current) => ({ ...current, startNewTxOnDispatch: event.target.checked })),
4597
+ "data-testid": "processor-start-new-tx"
4598
+ }
4599
+ ),
4600
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Start new transaction on dispatch" })
4601
+ ]
4602
+ }
4603
+ ),
4604
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: checkboxRowStyle, children: [
4605
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4331
4606
  "input",
4332
4607
  {
4333
4608
  type: "checkbox",
@@ -4335,9 +4610,9 @@ function ProcessorEditorModal({
4335
4610
  onChange: (event) => setDraft((current) => ({ ...current, attachEntity: event.target.checked }))
4336
4611
  }
4337
4612
  ),
4338
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Attach entity" })
4613
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Attach entity" })
4339
4614
  ] }),
4340
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4615
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4341
4616
  "input",
4342
4617
  {
4343
4618
  type: "text",
@@ -4350,7 +4625,7 @@ function ProcessorEditorModal({
4350
4625
  style: inputStyle2
4351
4626
  }
4352
4627
  ) }),
4353
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4628
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4354
4629
  "input",
4355
4630
  {
4356
4631
  type: "text",
@@ -4362,17 +4637,33 @@ function ProcessorEditorModal({
4362
4637
  style: inputStyle2
4363
4638
  }
4364
4639
  ) }),
4365
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Retry policy", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4640
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Retry policy", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4641
+ CustomSelectInput,
4642
+ {
4643
+ value: draft.retryPolicy,
4644
+ options: [
4645
+ { value: "", label: "Default (FIXED)" },
4646
+ { value: "NONE", label: "NONE" },
4647
+ { value: "FIXED", label: "FIXED" }
4648
+ ],
4649
+ onChange: (next) => setDraft((current) => ({ ...current, retryPolicy: next })),
4650
+ testId: "processor-retry-policy"
4651
+ }
4652
+ ) }),
4653
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Context", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4366
4654
  "input",
4367
4655
  {
4368
4656
  type: "text",
4369
- value: draft.retryPolicy,
4370
- onChange: (event) => setDraft((current) => ({ ...current, retryPolicy: event.target.value })),
4371
- style: inputStyle2
4657
+ value: draft.context,
4658
+ placeholder: "passed verbatim as request parameters",
4659
+ disabled,
4660
+ onChange: (event) => setDraft((current) => ({ ...current, context: event.target.value })),
4661
+ "data-testid": "processor-context-input",
4662
+ style: disabled ? disabledInputStyle : inputStyle2
4372
4663
  }
4373
4664
  ) }),
4374
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: checkboxRowStyle, children: [
4375
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4665
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: checkboxRowStyle, children: [
4666
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4376
4667
  "input",
4377
4668
  {
4378
4669
  type: "checkbox",
@@ -4385,9 +4676,9 @@ function ProcessorEditorModal({
4385
4676
  "data-testid": "processor-async-result"
4386
4677
  }
4387
4678
  ),
4388
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Async result" })
4679
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Async result" })
4389
4680
  ] }),
4390
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4681
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4391
4682
  "input",
4392
4683
  {
4393
4684
  type: "text",
@@ -4402,10 +4693,27 @@ function ProcessorEditorModal({
4402
4693
  }
4403
4694
  ) })
4404
4695
  ] }),
4405
- error && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "alert", style: errorStyle3, "data-testid": "processor-modal-error", children: error }),
4406
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("footer", { style: modalFooterStyle, children: [
4407
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4408
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4696
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4697
+ "div",
4698
+ {
4699
+ "data-testid": "processor-annotations",
4700
+ style: { display: "flex", flexDirection: "column", gap: 8, gridColumn: "1 / -1" },
4701
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4702
+ AnnotationsField,
4703
+ {
4704
+ value: draft.annotations,
4705
+ disabled,
4706
+ modelKey: `processor-${initialProcessor?.name ?? "new"}`,
4707
+ onCommit: (a) => setDraft((c) => ({ ...c, annotations: a })),
4708
+ onRemove: () => setDraft((c) => ({ ...c, annotations: void 0 }))
4709
+ }
4710
+ )
4711
+ }
4712
+ ),
4713
+ error && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "alert", style: errorStyle3, "data-testid": "processor-modal-error", children: error }),
4714
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("footer", { style: modalFooterStyle, children: [
4715
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4716
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4409
4717
  "button",
4410
4718
  {
4411
4719
  type: "button",
@@ -4423,8 +4731,8 @@ function FormField({
4423
4731
  label,
4424
4732
  children
4425
4733
  }) {
4426
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4427
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: labelStyle2, children: label }),
4734
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4735
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: labelStyle3, children: label }),
4428
4736
  children
4429
4737
  ] });
4430
4738
  }
@@ -4439,17 +4747,17 @@ function ProcessorForm({
4439
4747
  }) {
4440
4748
  const messages = useMessages();
4441
4749
  const [modalOpen, setModalOpen] = (0, import_react14.useState)(false);
4442
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: summaryCardStyle, children: [
4443
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4444
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4445
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
4446
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4750
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: summaryCardStyle, children: [
4751
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4752
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4753
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
4754
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4447
4755
  ] }),
4448
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: chipStyle, children: processor.type })
4756
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: chipStyle, children: processor.type })
4449
4757
  ] }),
4450
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4451
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4452
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4758
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4759
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4760
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4453
4761
  "button",
4454
4762
  {
4455
4763
  type: "button",
@@ -4464,7 +4772,7 @@ function ProcessorForm({
4464
4772
  children: messages.inspector.moveUp
4465
4773
  }
4466
4774
  ),
4467
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4775
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4468
4776
  "button",
4469
4777
  {
4470
4778
  type: "button",
@@ -4479,7 +4787,7 @@ function ProcessorForm({
4479
4787
  children: messages.inspector.moveDown
4480
4788
  }
4481
4789
  ),
4482
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4790
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4483
4791
  "button",
4484
4792
  {
4485
4793
  type: "button",
@@ -4491,7 +4799,7 @@ function ProcessorForm({
4491
4799
  }
4492
4800
  )
4493
4801
  ] }),
4494
- modalOpen && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4802
+ modalOpen && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4495
4803
  ProcessorEditorModal,
4496
4804
  {
4497
4805
  title: `Edit ${processor.name}`,
@@ -4511,7 +4819,7 @@ function ProcessorForm({
4511
4819
  )
4512
4820
  ] });
4513
4821
  }
4514
- var labelStyle2 = {
4822
+ var labelStyle3 = {
4515
4823
  fontSize: 12,
4516
4824
  color: colors.textSecondary,
4517
4825
  marginBottom: 2
@@ -4605,7 +4913,7 @@ var summaryCardStyle = {
4605
4913
  };
4606
4914
 
4607
4915
  // src/inspector/TransitionForm.tsx
4608
- var import_jsx_runtime15 = require("react/jsx-runtime");
4916
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4609
4917
  function TransitionForm({
4610
4918
  workflow,
4611
4919
  stateCode,
@@ -4726,9 +5034,9 @@ function TransitionForm({
4726
5034
  index: index + 1
4727
5035
  });
4728
5036
  };
4729
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: transitionFormStyle, children: [
4730
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
4731
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5037
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: transitionFormStyle, children: [
5038
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
5039
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4732
5040
  TextField,
4733
5041
  {
4734
5042
  label: messages.inspector.name,
@@ -4739,90 +5047,96 @@ function TransitionForm({
4739
5047
  testId: "inspector-transition-name"
4740
5048
  }
4741
5049
  ),
4742
- renameError && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4743
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4744
- SelectField,
4745
- {
4746
- label: "Source state",
4747
- value: stateCode,
4748
- options: stateOptions,
4749
- disabled,
4750
- onChange: (toState) => {
4751
- if (toState === stateCode) return;
4752
- onDispatch({
4753
- op: "moveTransitionSource",
4754
- workflow: workflow.name,
4755
- fromState: stateCode,
4756
- toState,
4757
- transitionName: transition.name
4758
- });
4759
- },
4760
- testId: "inspector-transition-source-state"
4761
- }
4762
- ),
4763
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4764
- SelectField,
4765
- {
4766
- label: "Target state",
4767
- value: transition.next,
4768
- options: stateOptions,
4769
- disabled,
4770
- onChange: (next) => update({ next }),
4771
- testId: "inspector-transition-next"
4772
- }
4773
- ),
4774
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4775
- SelectField,
4776
- {
4777
- label: messages.inspector.transitionType,
4778
- value: transition.manual ? "manual" : "automated",
4779
- options: [
4780
- { value: "automated", label: messages.inspector.automated },
4781
- { value: "manual", label: messages.inspector.manual }
4782
- ],
4783
- disabled,
4784
- onChange: (next) => update({ manual: next === "manual" }),
4785
- testId: "inspector-transition-manual"
4786
- }
4787
- ),
4788
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4789
- CheckboxField,
4790
- {
4791
- label: messages.inspector.disabled,
4792
- checked: transition.disabled,
4793
- disabled,
4794
- onChange: (next) => update({ disabled: next }),
4795
- testId: "inspector-transition-disabled"
4796
- }
4797
- ),
4798
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4799
- AnchorSelect,
4800
- {
4801
- label: messages.inspector.sourceAnchor,
4802
- value: anchors?.source,
4803
- disabled,
4804
- messages,
4805
- onChange: (next) => setAnchor("source", next),
4806
- testId: "inspector-transition-source-anchor"
4807
- }
4808
- ),
4809
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4810
- AnchorSelect,
4811
- {
4812
- label: messages.inspector.targetAnchor,
4813
- value: anchors?.target,
4814
- disabled,
4815
- messages,
4816
- onChange: (next) => setAnchor("target", next),
4817
- testId: "inspector-transition-target-anchor"
4818
- }
4819
- ),
4820
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4821
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 6 }, children: [
4822
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
4823
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
5050
+ renameError && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
5051
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: twoColStyle, children: [
5052
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5053
+ SelectField,
5054
+ {
5055
+ label: "Source state",
5056
+ value: stateCode,
5057
+ options: stateOptions,
5058
+ disabled,
5059
+ onChange: (toState) => {
5060
+ if (toState === stateCode) return;
5061
+ onDispatch({
5062
+ op: "moveTransitionSource",
5063
+ workflow: workflow.name,
5064
+ fromState: stateCode,
5065
+ toState,
5066
+ transitionName: transition.name
5067
+ });
5068
+ },
5069
+ testId: "inspector-transition-source-state"
5070
+ }
5071
+ ),
5072
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5073
+ SelectField,
5074
+ {
5075
+ label: "Target state",
5076
+ value: transition.next,
5077
+ options: stateOptions,
5078
+ disabled,
5079
+ onChange: (next) => update({ next }),
5080
+ testId: "inspector-transition-next"
5081
+ }
5082
+ )
5083
+ ] }),
5084
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: twoColStyle, children: [
5085
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5086
+ SelectField,
5087
+ {
5088
+ label: messages.inspector.transitionType,
5089
+ value: transition.manual ? "manual" : "automated",
5090
+ options: [
5091
+ { value: "automated", label: messages.inspector.automated },
5092
+ { value: "manual", label: messages.inspector.manual }
5093
+ ],
5094
+ disabled,
5095
+ onChange: (next) => update({ manual: next === "manual" }),
5096
+ testId: "inspector-transition-manual"
5097
+ }
5098
+ ),
5099
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5100
+ CheckboxField,
5101
+ {
5102
+ label: messages.inspector.disabled,
5103
+ checked: transition.disabled,
5104
+ disabled,
5105
+ onChange: (next) => update({ disabled: next }),
5106
+ testId: "inspector-transition-disabled"
5107
+ }
5108
+ )
5109
+ ] }),
5110
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: twoColStyle, children: [
5111
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5112
+ AnchorSelect,
5113
+ {
5114
+ label: messages.inspector.sourceAnchor,
5115
+ value: anchors?.source,
5116
+ disabled,
5117
+ messages,
5118
+ onChange: (next) => setAnchor("source", next),
5119
+ testId: "inspector-transition-source-anchor"
5120
+ }
5121
+ ),
5122
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5123
+ AnchorSelect,
5124
+ {
5125
+ label: messages.inspector.targetAnchor,
5126
+ value: anchors?.target,
5127
+ disabled,
5128
+ messages,
5129
+ onChange: (next) => setAnchor("target", next),
5130
+ testId: "inspector-transition-target-anchor"
5131
+ }
5132
+ )
5133
+ ] }),
5134
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
5135
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", gap: 6 }, children: [
5136
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
5137
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
4824
5138
  ] }),
4825
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5139
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4826
5140
  "p",
4827
5141
  {
4828
5142
  style: {
@@ -4836,8 +5150,8 @@ function TransitionForm({
4836
5150
  }
4837
5151
  )
4838
5152
  ] }),
4839
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4840
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5153
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
5154
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4841
5155
  "button",
4842
5156
  {
4843
5157
  type: "button",
@@ -4848,8 +5162,8 @@ function TransitionForm({
4848
5162
  children: "Delete transition"
4849
5163
  }
4850
5164
  ),
4851
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4852
- issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5165
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
5166
+ issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4853
5167
  "div",
4854
5168
  {
4855
5169
  role: "alert",
@@ -4866,12 +5180,12 @@ function TransitionForm({
4866
5180
  `${issue.code}-${i}`
4867
5181
  )) })
4868
5182
  ] }),
4869
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5183
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4870
5184
  TransitionSection,
4871
5185
  {
4872
5186
  title: messages.inspector.criteria,
4873
5187
  testId: "inspector-transition-criteria-section",
4874
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5188
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4875
5189
  CriterionSection,
4876
5190
  {
4877
5191
  host,
@@ -4880,6 +5194,7 @@ function TransitionForm({
4880
5194
  targetState: transition.next,
4881
5195
  manual: transition.manual,
4882
5196
  criterion: transition.criterion,
5197
+ criterionAnnotations: transition.criterionAnnotations,
4883
5198
  disabled,
4884
5199
  onDispatch,
4885
5200
  onSelectionChange
@@ -4887,18 +5202,18 @@ function TransitionForm({
4887
5202
  )
4888
5203
  }
4889
5204
  ),
4890
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5205
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4891
5206
  TransitionSection,
4892
5207
  {
4893
5208
  title: "Scheduled transition",
4894
5209
  testId: "inspector-transition-schedule-section",
4895
5210
  children: [
4896
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5211
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4897
5212
  "label",
4898
5213
  {
4899
5214
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: 8, fontSize: 12, color: colors.textSecondary, cursor: "pointer" },
4900
5215
  children: [
4901
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5216
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4902
5217
  "input",
4903
5218
  {
4904
5219
  type: "checkbox",
@@ -4918,14 +5233,14 @@ function TransitionForm({
4918
5233
  }
4919
5234
  }
4920
5235
  ),
4921
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Enable schedule" })
5236
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Enable schedule" })
4922
5237
  ]
4923
5238
  }
4924
5239
  ),
4925
- transition.schedule !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
4926
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4927
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
4928
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5240
+ transition.schedule !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: twoColStyle, children: [
5241
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5242
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
5243
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4929
5244
  "input",
4930
5245
  {
4931
5246
  type: "text",
@@ -4941,9 +5256,9 @@ function TransitionForm({
4941
5256
  }
4942
5257
  )
4943
5258
  ] }),
4944
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4945
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
4946
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5259
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5260
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
5261
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4947
5262
  "input",
4948
5263
  {
4949
5264
  type: "text",
@@ -4960,7 +5275,7 @@ function TransitionForm({
4960
5275
  )
4961
5276
  ] })
4962
5277
  ] }),
4963
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5278
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4964
5279
  "p",
4965
5280
  {
4966
5281
  style: {
@@ -4980,28 +5295,28 @@ function TransitionForm({
4980
5295
  ]
4981
5296
  }
4982
5297
  ),
4983
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5298
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4984
5299
  TransitionSection,
4985
5300
  {
4986
5301
  title: messages.inspector.processors,
4987
5302
  testId: "inspector-transition-processes-section",
4988
5303
  children: [
4989
- processorCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
4990
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
4991
- processors.map((processor, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: processorRowStyle, children: [
4992
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
4993
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { style: processorOrderStyle, children: [
5304
+ processorCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
5305
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
5306
+ processors.map((processor, index) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: processorRowStyle, children: [
5307
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
5308
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { style: processorOrderStyle, children: [
4994
5309
  index + 1,
4995
5310
  "."
4996
5311
  ] }),
4997
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: processorTypeChipStyle, children: processor.type }),
4998
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
4999
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
5000
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
5312
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: processorTypeChipStyle, children: processor.type }),
5313
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
5314
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
5315
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
5001
5316
  ] })
5002
5317
  ] }),
5003
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5004
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5318
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5319
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5005
5320
  "button",
5006
5321
  {
5007
5322
  type: "button",
@@ -5016,7 +5331,7 @@ function TransitionForm({
5016
5331
  children: "Edit"
5017
5332
  }
5018
5333
  ),
5019
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5334
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5020
5335
  "button",
5021
5336
  {
5022
5337
  type: "button",
@@ -5027,7 +5342,7 @@ function TransitionForm({
5027
5342
  children: "Duplicate"
5028
5343
  }
5029
5344
  ),
5030
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5345
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5031
5346
  "button",
5032
5347
  {
5033
5348
  type: "button",
@@ -5043,7 +5358,7 @@ function TransitionForm({
5043
5358
  children: "Move up"
5044
5359
  }
5045
5360
  ),
5046
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5361
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5047
5362
  "button",
5048
5363
  {
5049
5364
  type: "button",
@@ -5059,7 +5374,7 @@ function TransitionForm({
5059
5374
  children: "Move down"
5060
5375
  }
5061
5376
  ),
5062
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5377
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5063
5378
  "button",
5064
5379
  {
5065
5380
  type: "button",
@@ -5073,7 +5388,7 @@ function TransitionForm({
5073
5388
  ] })
5074
5389
  ] }, processorUuids[index] ?? `${processor.name}-${index}`))
5075
5390
  ] }),
5076
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5391
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5077
5392
  "button",
5078
5393
  {
5079
5394
  type: "button",
@@ -5087,7 +5402,7 @@ function TransitionForm({
5087
5402
  ]
5088
5403
  }
5089
5404
  ),
5090
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5405
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5091
5406
  AnnotationsField,
5092
5407
  {
5093
5408
  value: transition.annotations,
@@ -5098,7 +5413,7 @@ function TransitionForm({
5098
5413
  onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid } })
5099
5414
  }
5100
5415
  ) }),
5101
- processorModal && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5416
+ processorModal && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5102
5417
  ProcessorEditorModal,
5103
5418
  {
5104
5419
  title: processorModal.mode === "add" ? "Add processor" : "Edit processor",
@@ -5118,8 +5433,8 @@ function TransitionSection({
5118
5433
  testId,
5119
5434
  children
5120
5435
  }) {
5121
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5122
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("header", { style: sectionHeaderStyle, children: title }),
5436
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5437
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("header", { style: sectionHeaderStyle, children: title }),
5123
5438
  children
5124
5439
  ] });
5125
5440
  }
@@ -5128,6 +5443,12 @@ var transitionFormStyle = {
5128
5443
  flexDirection: "column",
5129
5444
  gap: 16
5130
5445
  };
5446
+ var twoColStyle = {
5447
+ display: "grid",
5448
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
5449
+ gap: 8,
5450
+ alignItems: "end"
5451
+ };
5131
5452
  var transitionSectionStyle = {
5132
5453
  display: "flex",
5133
5454
  flexDirection: "column",
@@ -5226,9 +5547,9 @@ function AnchorSelect({
5226
5547
  { value: "left", label: messages.inspector.anchorLeft },
5227
5548
  { value: "left-bottom", label: messages.inspector.anchorLeftBottom }
5228
5549
  ];
5229
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5230
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: label }),
5231
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5550
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5551
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { fontWeight: 500 }, children: label }),
5552
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5232
5553
  CustomSelectInput,
5233
5554
  {
5234
5555
  value: value ?? "",
@@ -5243,7 +5564,7 @@ function AnchorSelect({
5243
5564
  }
5244
5565
 
5245
5566
  // src/inspector/Inspector.tsx
5246
- var import_jsx_runtime16 = require("react/jsx-runtime");
5567
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5247
5568
  function issueKeyForSelection(selection) {
5248
5569
  if (!selection) return null;
5249
5570
  switch (selection.kind) {
@@ -5283,7 +5604,7 @@ function Inspector({
5283
5604
  return issues.filter((i) => i.targetId === selectionIssueKey);
5284
5605
  }, [issues, selectionIssueKey]);
5285
5606
  const breadcrumb = renderBreadcrumb(resolved);
5286
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5607
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5287
5608
  "aside",
5288
5609
  {
5289
5610
  style: {
@@ -5299,7 +5620,7 @@ function Inspector({
5299
5620
  },
5300
5621
  "data-testid": "inspector",
5301
5622
  children: [
5302
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5623
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5303
5624
  "header",
5304
5625
  {
5305
5626
  "data-inspector-drag-handle": true,
@@ -5313,8 +5634,8 @@ function Inspector({
5313
5634
  gap: 8
5314
5635
  },
5315
5636
  children: [
5316
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5317
- onToggleDock && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5637
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5638
+ onToggleDock && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5318
5639
  "button",
5319
5640
  {
5320
5641
  type: "button",
@@ -5339,7 +5660,7 @@ function Inspector({
5339
5660
  children: docked ? "\u2922" : "\u2921"
5340
5661
  }
5341
5662
  ),
5342
- onMinimize && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5663
+ onMinimize && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5343
5664
  "button",
5344
5665
  {
5345
5666
  type: "button",
@@ -5365,7 +5686,7 @@ function Inspector({
5365
5686
  children: "\u2013"
5366
5687
  }
5367
5688
  ),
5368
- onClose && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5689
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5369
5690
  "button",
5370
5691
  {
5371
5692
  type: "button",
@@ -5393,8 +5714,8 @@ function Inspector({
5393
5714
  ]
5394
5715
  }
5395
5716
  ),
5396
- developerMode && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5397
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5717
+ developerMode && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5718
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5398
5719
  TabButton,
5399
5720
  {
5400
5721
  active: effectiveTab === "properties",
@@ -5403,7 +5724,7 @@ function Inspector({
5403
5724
  children: messages.inspector.properties
5404
5725
  }
5405
5726
  ),
5406
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5727
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5407
5728
  TabButton,
5408
5729
  {
5409
5730
  active: effectiveTab === "json",
@@ -5413,11 +5734,11 @@ function Inspector({
5413
5734
  }
5414
5735
  )
5415
5736
  ] }),
5416
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5417
- effectiveTab === "properties" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
5418
- !resolved && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(EmptyState, { message: messages.inspector.empty }),
5419
- resolved?.kind === "workflow" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5420
- resolved?.kind === "state" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5737
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5738
+ effectiveTab === "properties" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
5739
+ !resolved && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(EmptyState, { message: messages.inspector.empty }),
5740
+ resolved?.kind === "workflow" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5741
+ resolved?.kind === "state" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5421
5742
  StateForm,
5422
5743
  {
5423
5744
  workflow: resolved.workflow,
@@ -5430,7 +5751,7 @@ function Inspector({
5430
5751
  },
5431
5752
  `${resolved.workflow.name}:${resolved.stateCode}`
5432
5753
  ),
5433
- resolved?.kind === "transition" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5754
+ resolved?.kind === "transition" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5434
5755
  TransitionForm,
5435
5756
  {
5436
5757
  workflow: resolved.workflow,
@@ -5447,7 +5768,7 @@ function Inspector({
5447
5768
  },
5448
5769
  resolved.transitionUuid
5449
5770
  ),
5450
- resolved?.kind === "processor" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5771
+ resolved?.kind === "processor" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5451
5772
  ProcessorForm,
5452
5773
  {
5453
5774
  processor: resolved.processor,
@@ -5461,8 +5782,8 @@ function Inspector({
5461
5782
  resolved.processorUuid
5462
5783
  )
5463
5784
  ] }),
5464
- developerMode && effectiveTab === "json" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(JsonPreview, { document: doc, resolved }),
5465
- selectionIssues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5785
+ developerMode && effectiveTab === "json" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(JsonPreview, { document: doc, resolved }),
5786
+ selectionIssues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5466
5787
  ] })
5467
5788
  ]
5468
5789
  }
@@ -5485,7 +5806,7 @@ function TabButton({
5485
5806
  children,
5486
5807
  testId
5487
5808
  }) {
5488
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5809
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5489
5810
  "button",
5490
5811
  {
5491
5812
  type: "button",
@@ -5506,17 +5827,17 @@ function TabButton({
5506
5827
  );
5507
5828
  }
5508
5829
  function EmptyState({ message }) {
5509
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5830
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5510
5831
  }
5511
5832
  function IssuesList({
5512
5833
  issues,
5513
5834
  title
5514
5835
  }) {
5515
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5516
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5836
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5837
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5517
5838
  issues.map((issue, i) => {
5518
5839
  const tone = severityTone(issue.severity);
5519
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5840
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5520
5841
  "div",
5521
5842
  {
5522
5843
  style: {
@@ -5527,8 +5848,8 @@ function IssuesList({
5527
5848
  fontSize: 12
5528
5849
  },
5529
5850
  children: [
5530
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: issue.code }),
5531
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: issue.message })
5851
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: issue.code }),
5852
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { children: issue.message })
5532
5853
  ]
5533
5854
  },
5534
5855
  `${issue.code}-${i}`
@@ -5548,7 +5869,7 @@ function JsonPreview({
5548
5869
  if (resolved.kind === "processor") return JSON.stringify(resolved.processor, null, 2);
5549
5870
  return "";
5550
5871
  }, [doc, resolved]);
5551
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5872
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5552
5873
  "pre",
5553
5874
  {
5554
5875
  style: {
@@ -5606,7 +5927,7 @@ function savePlacement(base, p) {
5606
5927
  }
5607
5928
 
5608
5929
  // src/inspector/InspectorFrame.tsx
5609
- var import_jsx_runtime17 = require("react/jsx-runtime");
5930
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5610
5931
  var FLOATING_Z = 40;
5611
5932
  var MIN_BAR_Z = 50;
5612
5933
  function InspectorFrame({
@@ -5674,8 +5995,8 @@ function InspectorFrame({
5674
5995
  overflow: "hidden",
5675
5996
  display: minimized ? "none" : "flex"
5676
5997
  } : { position: "relative", flex: `0 0 ${dockedWidth}px`, width: dockedWidth, height: "100%", display: "flex" };
5677
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
5678
- mode === "docked" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5998
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5999
+ mode === "docked" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5679
6000
  "div",
5680
6001
  {
5681
6002
  "data-testid": "inspector-resize-handle",
@@ -5685,7 +6006,7 @@ function InspectorFrame({
5685
6006
  onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
5686
6007
  }
5687
6008
  ),
5688
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
6009
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5689
6010
  "div",
5690
6011
  {
5691
6012
  "data-testid": "inspector-frame",
@@ -5693,7 +6014,7 @@ function InspectorFrame({
5693
6014
  style,
5694
6015
  children: [
5695
6016
  children,
5696
- floating && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6017
+ floating && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5697
6018
  "div",
5698
6019
  {
5699
6020
  "data-testid": "inspector-resize-grip",
@@ -5704,7 +6025,7 @@ function InspectorFrame({
5704
6025
  ]
5705
6026
  }
5706
6027
  ),
5707
- minimized && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
6028
+ minimized && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5708
6029
  "div",
5709
6030
  {
5710
6031
  "data-testid": "inspector-min-bar",
@@ -5712,9 +6033,9 @@ function InspectorFrame({
5712
6033
  title: messages.inspector.restore,
5713
6034
  style: minBarStyle,
5714
6035
  children: [
5715
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colors.primary, flex: "0 0 auto" } }),
5716
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12, color: colors.textSecondary }, children: messages.inspector.minimizedTitle }),
5717
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6036
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colors.primary, flex: "0 0 auto" } }),
6037
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12, color: colors.textSecondary }, children: messages.inspector.minimizedTitle }),
6038
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5718
6039
  "button",
5719
6040
  {
5720
6041
  type: "button",
@@ -5729,7 +6050,7 @@ function InspectorFrame({
5729
6050
  children: "\u2922"
5730
6051
  }
5731
6052
  ),
5732
- onClose && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6053
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5733
6054
  "button",
5734
6055
  {
5735
6056
  type: "button",
@@ -5784,7 +6105,7 @@ var barBtnStyle = {
5784
6105
  };
5785
6106
 
5786
6107
  // src/toolbar/Toolbar.tsx
5787
- var import_jsx_runtime18 = require("react/jsx-runtime");
6108
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5788
6109
  function Toolbar({
5789
6110
  derived,
5790
6111
  readOnly,
@@ -5798,7 +6119,7 @@ function Toolbar({
5798
6119
  toolbarEnd
5799
6120
  }) {
5800
6121
  const messages = useMessages();
5801
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
6122
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5802
6123
  "footer",
5803
6124
  {
5804
6125
  style: {
@@ -5813,11 +6134,11 @@ function Toolbar({
5813
6134
  },
5814
6135
  "data-testid": "toolbar",
5815
6136
  children: [
5816
- toolbarStart && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
5817
- toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
5818
- !toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { flex: 1 } }),
5819
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
5820
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6137
+ toolbarStart && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
6138
+ toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
6139
+ !toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { flex: 1 } }),
6140
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
6141
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5821
6142
  ValidationPill,
5822
6143
  {
5823
6144
  severity: "error",
@@ -5829,7 +6150,7 @@ function Toolbar({
5829
6150
  testId: "toolbar-errors"
5830
6151
  }
5831
6152
  ),
5832
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6153
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5833
6154
  ValidationPill,
5834
6155
  {
5835
6156
  severity: "warning",
@@ -5841,7 +6162,7 @@ function Toolbar({
5841
6162
  testId: "toolbar-warnings"
5842
6163
  }
5843
6164
  ),
5844
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6165
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5845
6166
  ValidationPill,
5846
6167
  {
5847
6168
  severity: "info",
@@ -5854,7 +6175,7 @@ function Toolbar({
5854
6175
  }
5855
6176
  )
5856
6177
  ] }),
5857
- onSave && showSaveButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6178
+ onSave && showSaveButton && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5858
6179
  "button",
5859
6180
  {
5860
6181
  type: "button",
@@ -5865,7 +6186,7 @@ function Toolbar({
5865
6186
  children: messages.toolbar.save
5866
6187
  }
5867
6188
  ),
5868
- toolbarEnd && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
6189
+ toolbarEnd && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5869
6190
  ]
5870
6191
  }
5871
6192
  );
@@ -5887,7 +6208,7 @@ function ValidationPill({
5887
6208
  const tone = severityTone(severity);
5888
6209
  const interactive = count > 0 && !!onClick;
5889
6210
  const hasIssues = count > 0;
5890
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
6211
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5891
6212
  "button",
5892
6213
  {
5893
6214
  type: "button",
@@ -5914,7 +6235,7 @@ function ValidationPill({
5914
6235
  height: 20
5915
6236
  },
5916
6237
  children: [
5917
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
6238
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5918
6239
  count
5919
6240
  ]
5920
6241
  }
@@ -5939,7 +6260,7 @@ var slotStyle = {
5939
6260
 
5940
6261
  // src/toolbar/IssuesDrawer.tsx
5941
6262
  var import_react17 = require("react");
5942
- var import_jsx_runtime19 = require("react/jsx-runtime");
6263
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5943
6264
  function resolveTarget(doc, targetId) {
5944
6265
  if (!targetId) return null;
5945
6266
  const ids = doc.meta.ids;
@@ -6028,7 +6349,7 @@ function IssuesDrawer({
6028
6349
  }, [severity, messages]);
6029
6350
  const tone = severityTone(severity);
6030
6351
  if (!open) return null;
6031
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6352
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6032
6353
  "div",
6033
6354
  {
6034
6355
  ref,
@@ -6052,7 +6373,7 @@ function IssuesDrawer({
6052
6373
  flexDirection: "column"
6053
6374
  },
6054
6375
  children: [
6055
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6376
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6056
6377
  "header",
6057
6378
  {
6058
6379
  style: {
@@ -6063,7 +6384,7 @@ function IssuesDrawer({
6063
6384
  gap: 8
6064
6385
  },
6065
6386
  children: [
6066
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6387
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6067
6388
  "span",
6068
6389
  {
6069
6390
  style: {
@@ -6076,12 +6397,12 @@ function IssuesDrawer({
6076
6397
  "aria-hidden": true
6077
6398
  }
6078
6399
  ),
6079
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6400
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6080
6401
  title,
6081
6402
  " \xB7 ",
6082
6403
  filtered.length
6083
6404
  ] }),
6084
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6405
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6085
6406
  "button",
6086
6407
  {
6087
6408
  type: "button",
@@ -6104,14 +6425,14 @@ function IssuesDrawer({
6104
6425
  ]
6105
6426
  }
6106
6427
  ),
6107
- filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6428
+ filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6108
6429
  "p",
6109
6430
  {
6110
6431
  style: { padding: 12, color: colors.textTertiary, fontSize: 12, margin: 0 },
6111
6432
  "data-testid": "issues-drawer-empty",
6112
6433
  children: messages.issues.none
6113
6434
  }
6114
- ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6435
+ ) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6115
6436
  "ul",
6116
6437
  {
6117
6438
  style: {
@@ -6125,7 +6446,7 @@ function IssuesDrawer({
6125
6446
  children: filtered.map((issue, idx) => {
6126
6447
  const target = resolveTarget(doc, issue.targetId);
6127
6448
  const targetLabel = target ? target.kind === "transition" ? `${messages.issues.relatedTransition}: ${target.label}` : target.kind === "state" ? `${messages.issues.relatedState}: ${target.label}` : target.label : null;
6128
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6449
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6129
6450
  "li",
6130
6451
  {
6131
6452
  style: {
@@ -6139,10 +6460,10 @@ function IssuesDrawer({
6139
6460
  },
6140
6461
  "data-testid": `issues-drawer-item-${idx}`,
6141
6462
  children: [
6142
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
6143
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
6144
- targetLabel && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
6145
- target && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6463
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
6464
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
6465
+ targetLabel && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
6466
+ target && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6146
6467
  "button",
6147
6468
  {
6148
6469
  type: "button",
@@ -6182,7 +6503,7 @@ var import_react19 = require("react");
6182
6503
  // src/toolbar/VersionBadge.tsx
6183
6504
  var import_react18 = require("react");
6184
6505
  var import_react_dom2 = require("react-dom");
6185
- var import_jsx_runtime20 = require("react/jsx-runtime");
6506
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6186
6507
  function VersionBadge({
6187
6508
  version,
6188
6509
  supportedVersions,
@@ -6215,7 +6536,7 @@ function VersionBadge({
6215
6536
  setOpen((o) => !o);
6216
6537
  };
6217
6538
  if (readOnly) {
6218
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6539
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6219
6540
  "div",
6220
6541
  {
6221
6542
  "data-testid": "version-badge",
@@ -6234,7 +6555,7 @@ function VersionBadge({
6234
6555
  );
6235
6556
  }
6236
6557
  const dropdown = open && dropdownPos ? (0, import_react_dom2.createPortal)(
6237
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6558
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6238
6559
  "div",
6239
6560
  {
6240
6561
  ref: dropdownRef,
@@ -6253,7 +6574,7 @@ function VersionBadge({
6253
6574
  zIndex: 9999
6254
6575
  },
6255
6576
  children: [
6256
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6577
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6257
6578
  "div",
6258
6579
  {
6259
6580
  style: {
@@ -6270,7 +6591,7 @@ function VersionBadge({
6270
6591
  ),
6271
6592
  [...supportedVersions].reverse().map((v) => {
6272
6593
  const isCurrent = v === version.replace(/^v/, "");
6273
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6594
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6274
6595
  "button",
6275
6596
  {
6276
6597
  type: "button",
@@ -6293,16 +6614,16 @@ function VersionBadge({
6293
6614
  textAlign: "left"
6294
6615
  },
6295
6616
  children: [
6296
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { children: [
6617
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { children: [
6297
6618
  v,
6298
6619
  " ",
6299
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6620
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6300
6621
  "cyoda-go ",
6301
6622
  v,
6302
6623
  ".x"
6303
6624
  ] })
6304
6625
  ] }),
6305
- isCurrent && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6626
+ isCurrent && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6306
6627
  "span",
6307
6628
  {
6308
6629
  style: {
@@ -6326,8 +6647,8 @@ function VersionBadge({
6326
6647
  ),
6327
6648
  document.body
6328
6649
  ) : null;
6329
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6330
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6650
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6651
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6331
6652
  "button",
6332
6653
  {
6333
6654
  ref: buttonRef,
@@ -6350,7 +6671,7 @@ function VersionBadge({
6350
6671
  },
6351
6672
  children: [
6352
6673
  version,
6353
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6674
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6354
6675
  ]
6355
6676
  }
6356
6677
  ),
@@ -6359,7 +6680,7 @@ function VersionBadge({
6359
6680
  }
6360
6681
 
6361
6682
  // src/toolbar/WorkflowTabs.tsx
6362
- var import_jsx_runtime21 = require("react/jsx-runtime");
6683
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6363
6684
  function WorkflowTabs({
6364
6685
  workflows,
6365
6686
  activeWorkflow,
@@ -6396,7 +6717,7 @@ function WorkflowTabs({
6396
6717
  setEditingTab(null);
6397
6718
  };
6398
6719
  const cancelEdit = () => setEditingTab(null);
6399
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6720
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6400
6721
  "nav",
6401
6722
  {
6402
6723
  style: {
@@ -6414,7 +6735,7 @@ function WorkflowTabs({
6414
6735
  workflows.map((w) => {
6415
6736
  const active = w.name === activeWorkflow;
6416
6737
  const isEditing = editingTab === w.name;
6417
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6738
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6418
6739
  "div",
6419
6740
  {
6420
6741
  style: {
@@ -6425,7 +6746,7 @@ function WorkflowTabs({
6425
6746
  background: active ? "white" : "transparent"
6426
6747
  },
6427
6748
  children: [
6428
- isEditing ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6749
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6429
6750
  "input",
6430
6751
  {
6431
6752
  ref: inputRef,
@@ -6456,7 +6777,7 @@ function WorkflowTabs({
6456
6777
  width: Math.max(60, draftName.length * 8)
6457
6778
  }
6458
6779
  }
6459
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6780
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6460
6781
  "button",
6461
6782
  {
6462
6783
  type: "button",
@@ -6475,7 +6796,7 @@ function WorkflowTabs({
6475
6796
  children: w.name || messages.tabs.untitled
6476
6797
  }
6477
6798
  ),
6478
- onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6799
+ onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6479
6800
  "button",
6480
6801
  {
6481
6802
  type: "button",
@@ -6498,7 +6819,7 @@ function WorkflowTabs({
6498
6819
  w.name
6499
6820
  );
6500
6821
  }),
6501
- onAdd && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6822
+ onAdd && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6502
6823
  "button",
6503
6824
  {
6504
6825
  type: "button",
@@ -6523,9 +6844,9 @@ function WorkflowTabs({
6523
6844
  ]
6524
6845
  }
6525
6846
  ),
6526
- dialectVersion && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6527
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1 } }),
6528
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6847
+ dialectVersion && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
6848
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1 } }),
6849
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6529
6850
  VersionBadge,
6530
6851
  {
6531
6852
  version: dialectVersion,
@@ -6543,7 +6864,7 @@ function WorkflowTabs({
6543
6864
  // src/modals/DragConnectModal.tsx
6544
6865
  var import_react20 = require("react");
6545
6866
  var import_workflow_core9 = require("@cyoda/workflow-core");
6546
- var import_jsx_runtime22 = require("react/jsx-runtime");
6867
+ var import_jsx_runtime23 = require("react/jsx-runtime");
6547
6868
  function generateDefault(toState, existing) {
6548
6869
  const base = `to_${toState}`;
6549
6870
  if (!existing.has(base)) return base;
@@ -6564,16 +6885,16 @@ function DragConnectModal({
6564
6885
  const invalidFormat = !!name && !import_workflow_core9.NAME_REGEX.test(name);
6565
6886
  const duplicate = existing.has(name);
6566
6887
  const blocked = name.length === 0 || invalidFormat || duplicate;
6567
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ModalFrame, { onCancel, children: [
6568
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6569
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6888
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ModalFrame, { onCancel, children: [
6889
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6890
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6570
6891
  fromState,
6571
6892
  " \u2192 ",
6572
6893
  toState
6573
6894
  ] }),
6574
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6575
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6576
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6895
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6896
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6897
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6577
6898
  "input",
6578
6899
  {
6579
6900
  type: "text",
@@ -6593,11 +6914,11 @@ function DragConnectModal({
6593
6914
  }
6594
6915
  )
6595
6916
  ] }),
6596
- invalidFormat && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6597
- duplicate && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6598
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6599
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6600
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6917
+ invalidFormat && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6918
+ duplicate && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6919
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6920
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6921
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6601
6922
  "button",
6602
6923
  {
6603
6924
  type: "button",
@@ -6634,7 +6955,7 @@ var primaryBtn3 = {
6634
6955
  // src/modals/AddStateModal.tsx
6635
6956
  var import_react21 = require("react");
6636
6957
  var import_workflow_core10 = require("@cyoda/workflow-core");
6637
- var import_jsx_runtime23 = require("react/jsx-runtime");
6958
+ var import_jsx_runtime24 = require("react/jsx-runtime");
6638
6959
  function generateName(existing) {
6639
6960
  let n = 1;
6640
6961
  while (existing.includes(`state${n}`)) n++;
@@ -6662,11 +6983,11 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6662
6983
  }
6663
6984
  onCreate(name.trim());
6664
6985
  };
6665
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6666
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6667
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6668
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6669
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6986
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6987
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6988
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6989
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6990
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6670
6991
  "input",
6671
6992
  {
6672
6993
  ref: inputRef,
@@ -6692,7 +7013,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6692
7013
  }
6693
7014
  }
6694
7015
  ),
6695
- error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7016
+ error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6696
7017
  "div",
6697
7018
  {
6698
7019
  id: "add-state-error",
@@ -6702,8 +7023,8 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6702
7023
  }
6703
7024
  )
6704
7025
  ] }),
6705
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6706
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7026
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
7027
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6707
7028
  "button",
6708
7029
  {
6709
7030
  type: "button",
@@ -6713,7 +7034,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6713
7034
  children: "Cancel"
6714
7035
  }
6715
7036
  ),
6716
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7037
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6717
7038
  "button",
6718
7039
  {
6719
7040
  type: "button",
@@ -6743,15 +7064,15 @@ var primaryBtn4 = {
6743
7064
 
6744
7065
  // src/modals/HelpModal.tsx
6745
7066
  var import_theme6 = require("@cyoda/workflow-viewer/theme");
6746
- var import_jsx_runtime24 = require("react/jsx-runtime");
7067
+ var import_jsx_runtime25 = require("react/jsx-runtime");
6747
7068
  function HelpModal({ onCancel }) {
6748
7069
  const messages = useMessages();
6749
7070
  const h = messages.help;
6750
7071
  const node = import_theme6.workflowPalette.node;
6751
7072
  const edge = import_theme6.workflowPalette.edge;
6752
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: 480, maxWidth: "85vw" }, children: [
6753
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
6754
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
7073
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { width: 480, maxWidth: "85vw" }, children: [
7074
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
7075
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6755
7076
  "div",
6756
7077
  {
6757
7078
  style: {
@@ -6764,48 +7085,46 @@ function HelpModal({ onCancel }) {
6764
7085
  gap: 16
6765
7086
  },
6766
7087
  children: [
6767
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.statesTitle, children: [
6768
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
6769
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
6770
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.processing.fill, border: node.processing.border, label: h.stateProcessing }),
6771
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.manualReview.fill, border: node.manualReview.border, label: h.stateManualReview }),
6772
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
6773
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
6774
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
7088
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: h.statesTitle, children: [
7089
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
7090
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
7091
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
7092
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
7093
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
6775
7094
  ] }),
6776
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.transitionsTitle, children: [
6777
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.automated, label: h.transitionAutomated }),
6778
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
6779
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.conditional, label: h.transitionConditional }),
6780
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.processing, label: h.transitionProcessing }),
6781
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
6782
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.loop, label: h.transitionLoop }),
6783
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.disabled, label: h.transitionDisabled })
7095
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: h.transitionsTitle, children: [
7096
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.automated, label: h.transitionAutomated }),
7097
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
7098
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.conditional, label: h.transitionConditional }),
7099
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.processing, label: h.transitionProcessing }),
7100
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
7101
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.loop, label: h.transitionLoop }),
7102
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LineRow, { color: edge.disabled, label: h.transitionDisabled })
6784
7103
  ] }),
6785
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.controlsTitle, children: [
6786
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
6787
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
6788
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
6789
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
6790
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
6791
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
6792
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
7104
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: h.controlsTitle, children: [
7105
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
7106
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
7107
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
7108
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
7109
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
7110
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
7111
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
6793
7112
  ] }),
6794
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Section, { title: h.tipsTitle, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
6795
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipDoubleClick }),
6796
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipConnect }),
6797
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipSelect }),
6798
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipMove })
7113
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Section, { title: h.tipsTitle, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
7114
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: h.tipDoubleClick }),
7115
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: h.tipConnect }),
7116
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: h.tipSelect }),
7117
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: h.tipMove })
6799
7118
  ] }) })
6800
7119
  ]
6801
7120
  }
6802
7121
  ),
6803
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
7122
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
6804
7123
  ] }) });
6805
7124
  }
6806
7125
  function Section({ title, children }) {
6807
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
6808
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7126
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
7127
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6809
7128
  "h3",
6810
7129
  {
6811
7130
  style: {
@@ -6819,12 +7138,12 @@ function Section({ title, children }) {
6819
7138
  children: title
6820
7139
  }
6821
7140
  ),
6822
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
7141
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6823
7142
  ] });
6824
7143
  }
6825
7144
  function ColorRow({ fill, border, label }) {
6826
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6827
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7145
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7146
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6828
7147
  "span",
6829
7148
  {
6830
7149
  style: {
@@ -6837,12 +7156,12 @@ function ColorRow({ fill, border, label }) {
6837
7156
  }
6838
7157
  }
6839
7158
  ),
6840
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
7159
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: label })
6841
7160
  ] });
6842
7161
  }
6843
7162
  function LineRow({ color, label, dashed }) {
6844
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6845
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7163
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7164
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6846
7165
  "line",
6847
7166
  {
6848
7167
  x1: "2",
@@ -6855,12 +7174,12 @@ function LineRow({ color, label, dashed }) {
6855
7174
  ...dashed ? { strokeDasharray: "3 3" } : {}
6856
7175
  }
6857
7176
  ) }),
6858
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
7177
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: label })
6859
7178
  ] });
6860
7179
  }
6861
7180
  function ShortcutRow({ keys, label }) {
6862
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6863
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7181
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7182
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6864
7183
  "kbd",
6865
7184
  {
6866
7185
  style: {
@@ -6880,12 +7199,12 @@ function ShortcutRow({ keys, label }) {
6880
7199
  children: keys
6881
7200
  }
6882
7201
  ),
6883
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
7202
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: label })
6884
7203
  ] });
6885
7204
  }
6886
7205
 
6887
7206
  // src/modals/VersionSwitchModal.tsx
6888
- var import_jsx_runtime25 = require("react/jsx-runtime");
7207
+ var import_jsx_runtime26 = require("react/jsx-runtime");
6889
7208
  function VersionSwitchModal({
6890
7209
  fromVersion,
6891
7210
  toVersion,
@@ -6893,7 +7212,7 @@ function VersionSwitchModal({
6893
7212
  onConfirm,
6894
7213
  onCancel
6895
7214
  }) {
6896
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7215
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6897
7216
  "div",
6898
7217
  {
6899
7218
  style: {
@@ -6905,7 +7224,7 @@ function VersionSwitchModal({
6905
7224
  justifyContent: "center",
6906
7225
  zIndex: 1e3
6907
7226
  },
6908
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
7227
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6909
7228
  "div",
6910
7229
  {
6911
7230
  "data-testid": "version-switch-modal",
@@ -6919,8 +7238,8 @@ function VersionSwitchModal({
6919
7238
  fontFamily: "inherit"
6920
7239
  },
6921
7240
  children: [
6922
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6923
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7241
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
7242
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6924
7243
  "div",
6925
7244
  {
6926
7245
  style: {
@@ -6937,20 +7256,20 @@ function VersionSwitchModal({
6937
7256
  children: "\u26A0\uFE0F"
6938
7257
  }
6939
7258
  ),
6940
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6941
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
7259
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
7260
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6942
7261
  "Switch to ",
6943
7262
  toVersion,
6944
7263
  "?"
6945
7264
  ] }),
6946
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
7265
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6947
7266
  "Switching to ",
6948
7267
  toVersion,
6949
7268
  " will remove data not supported in that dialect:"
6950
7269
  ] })
6951
7270
  ] })
6952
7271
  ] }),
6953
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
7272
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6954
7273
  "div",
6955
7274
  {
6956
7275
  style: {
@@ -6963,17 +7282,17 @@ function VersionSwitchModal({
6963
7282
  fontSize: 12
6964
7283
  },
6965
7284
  children: [
6966
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
6967
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: w }, i)) })
7285
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
7286
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: w }, i)) })
6968
7287
  ]
6969
7288
  }
6970
7289
  ),
6971
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
7290
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6972
7291
  "This cannot be undone. You can switch back to ",
6973
7292
  fromVersion,
6974
7293
  " any time, but the removed data will not be restored."
6975
7294
  ] }),
6976
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
7295
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6977
7296
  "div",
6978
7297
  {
6979
7298
  style: {
@@ -6985,7 +7304,7 @@ function VersionSwitchModal({
6985
7304
  marginTop: 16
6986
7305
  },
6987
7306
  children: [
6988
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7307
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6989
7308
  "button",
6990
7309
  {
6991
7310
  type: "button",
@@ -7003,7 +7322,7 @@ function VersionSwitchModal({
7003
7322
  children: "Cancel"
7004
7323
  }
7005
7324
  ),
7006
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
7325
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
7007
7326
  "button",
7008
7327
  {
7009
7328
  type: "button",
@@ -7038,7 +7357,7 @@ function VersionSwitchModal({
7038
7357
 
7039
7358
  // src/components/CommentNode.tsx
7040
7359
  var import_react22 = require("react");
7041
- var import_jsx_runtime26 = require("react/jsx-runtime");
7360
+ var import_jsx_runtime27 = require("react/jsx-runtime");
7042
7361
  function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7043
7362
  const [editing, setEditing] = (0, import_react22.useState)(false);
7044
7363
  const [draft, setDraft] = (0, import_react22.useState)(comment.text);
@@ -7047,7 +7366,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7047
7366
  setEditing(false);
7048
7367
  if (draft !== comment.text) onUpdate({ text: draft });
7049
7368
  };
7050
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
7369
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
7051
7370
  "div",
7052
7371
  {
7053
7372
  "data-testid": `comment-${comment.id}`,
@@ -7068,8 +7387,8 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7068
7387
  userSelect: "none"
7069
7388
  },
7070
7389
  children: [
7071
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7072
- !disabled && !editing && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
7390
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7391
+ !disabled && !editing && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7073
7392
  "button",
7074
7393
  {
7075
7394
  type: "button",
@@ -7084,7 +7403,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7084
7403
  children: "\u270F\uFE0F"
7085
7404
  }
7086
7405
  ),
7087
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
7406
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7088
7407
  "button",
7089
7408
  {
7090
7409
  type: "button",
@@ -7096,7 +7415,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7096
7415
  }
7097
7416
  )
7098
7417
  ] }),
7099
- editing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
7418
+ editing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7100
7419
  "textarea",
7101
7420
  {
7102
7421
  ref: textareaRef,
@@ -7122,7 +7441,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7122
7441
  },
7123
7442
  "data-testid": `comment-textarea-${comment.id}`
7124
7443
  }
7125
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
7444
+ ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7126
7445
  "div",
7127
7446
  {
7128
7447
  onDoubleClick: () => {
@@ -7132,7 +7451,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7132
7451
  }
7133
7452
  },
7134
7453
  style: { whiteSpace: "pre-wrap", wordBreak: "break-word", minHeight: 20 },
7135
- children: comment.text || /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("em", { style: { color: "#94a3b8" }, children: "empty note" })
7454
+ children: comment.text || /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("em", { style: { color: "#94a3b8" }, children: "empty note" })
7136
7455
  }
7137
7456
  )
7138
7457
  ]
@@ -7152,7 +7471,7 @@ var iconBtn = {
7152
7471
  // src/components/WorkflowJsonEditor.tsx
7153
7472
  var import_react23 = require("react");
7154
7473
  var import_workflow_monaco2 = require("@cyoda/workflow-monaco");
7155
- var import_jsx_runtime27 = require("react/jsx-runtime");
7474
+ var import_jsx_runtime28 = require("react/jsx-runtime");
7156
7475
  function WorkflowJsonEditor({
7157
7476
  document: document2,
7158
7477
  issues,
@@ -7277,7 +7596,7 @@ function WorkflowJsonEditor({
7277
7596
  return () => window.clearTimeout(timeout);
7278
7597
  }, [document2, selectedId, visible]);
7279
7598
  if (!config) {
7280
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7599
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7281
7600
  "div",
7282
7601
  {
7283
7602
  "data-testid": "workflow-json-unavailable",
@@ -7292,11 +7611,11 @@ function WorkflowJsonEditor({
7292
7611
  textAlign: "center",
7293
7612
  background: "#F8FAFC"
7294
7613
  },
7295
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UnavailableMessage, {})
7614
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UnavailableMessage, {})
7296
7615
  }
7297
7616
  );
7298
7617
  }
7299
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
7618
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7300
7619
  "div",
7301
7620
  {
7302
7621
  "data-testid": "workflow-json-editor",
@@ -7308,8 +7627,8 @@ function WorkflowJsonEditor({
7308
7627
  minHeight: 0
7309
7628
  },
7310
7629
  children: [
7311
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(JsonStatusBanner, { status }),
7312
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7630
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(JsonStatusBanner, { status }),
7631
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7313
7632
  "div",
7314
7633
  {
7315
7634
  ref: containerRef,
@@ -7322,7 +7641,7 @@ function WorkflowJsonEditor({
7322
7641
  }
7323
7642
  function UnavailableMessage() {
7324
7643
  const messages = useMessages();
7325
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: messages.editorView.unavailable });
7644
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_jsx_runtime28.Fragment, { children: messages.editorView.unavailable });
7326
7645
  }
7327
7646
  function JsonStatusBanner({ status }) {
7328
7647
  const messages = useMessages();
@@ -7331,7 +7650,7 @@ function JsonStatusBanner({ status }) {
7331
7650
  }
7332
7651
  const tone = status.status === "semantic-errors" ? { border: "#FCD34D", bg: "#FFFBEB", text: "#92400E" } : { border: "#FCA5A5", bg: "#FEF2F2", text: "#991B1B" };
7333
7652
  const body = status.status === "semantic-errors" ? messages.editorView.semanticErrors : status.status === "invalid-schema" ? messages.editorView.invalidSchema : `${messages.editorView.invalidJson}${status.message ? ` ${status.message}` : ""}`;
7334
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7653
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7335
7654
  "div",
7336
7655
  {
7337
7656
  role: "status",
@@ -7375,7 +7694,7 @@ function selectionFromJsonId(doc, id) {
7375
7694
  }
7376
7695
 
7377
7696
  // src/components/WorkflowEditor.tsx
7378
- var import_jsx_runtime28 = require("react/jsx-runtime");
7697
+ var import_jsx_runtime29 = require("react/jsx-runtime");
7379
7698
  function hasPersistedWorkflowUi(meta) {
7380
7699
  return !!meta && Object.values(meta).some((value) => value !== void 0);
7381
7700
  }
@@ -7451,6 +7770,9 @@ function WorkflowEditor({
7451
7770
  const [helpOpen, setHelpOpen] = (0, import_react24.useState)(false);
7452
7771
  const [reconnectError, setReconnectError] = (0, import_react24.useState)(null);
7453
7772
  const [layoutKey, setLayoutKey] = (0, import_react24.useState)(0);
7773
+ const [layoutPref, setLayoutPref] = (0, import_react24.useState)(
7774
+ () => loadLayoutPref(localStorageKey, layoutOptions)
7775
+ );
7454
7776
  const [activeSurface, setActiveSurface] = (0, import_react24.useState)("graph");
7455
7777
  const [jsonStatus, setJsonStatus] = (0, import_react24.useState)({ status: "idle" });
7456
7778
  const [openIssueSeverity, setOpenIssueSeverity] = (0, import_react24.useState)(null);
@@ -7634,6 +7956,30 @@ function WorkflowEditor({
7634
7956
  );
7635
7957
  setLayoutKey((k) => k + 1);
7636
7958
  }, [state.activeWorkflow, state.document, actions]);
7959
+ (0, import_react24.useEffect)(() => {
7960
+ saveLayoutPref(localStorageKey, layoutPref);
7961
+ }, [layoutPref, localStorageKey]);
7962
+ const propLayoutRef = (0, import_react24.useRef)({
7963
+ orientation: layoutOptions?.orientation,
7964
+ preset: layoutOptions?.preset
7965
+ });
7966
+ (0, import_react24.useEffect)(() => {
7967
+ const nextO = layoutOptions?.orientation;
7968
+ const nextP = layoutOptions?.preset;
7969
+ if (nextO === propLayoutRef.current.orientation && nextP === propLayoutRef.current.preset) return;
7970
+ propLayoutRef.current = { orientation: nextO, preset: nextP };
7971
+ setLayoutPref((prev) => ({
7972
+ orientation: nextO ?? prev.orientation,
7973
+ preset: nextP ?? prev.preset
7974
+ }));
7975
+ }, [layoutOptions?.orientation, layoutOptions?.preset]);
7976
+ const applyLayoutPref = (0, import_react24.useCallback)(
7977
+ (update) => {
7978
+ setLayoutPref((prev) => ({ ...prev, ...update }));
7979
+ handleAutoLayout();
7980
+ },
7981
+ [handleAutoLayout]
7982
+ );
7637
7983
  const openAddStateModal = (0, import_react24.useCallback)((position) => {
7638
7984
  const resolved = position ?? newStatePositionRef.current?.() ?? void 0;
7639
7985
  setPendingAddState(resolved ? { position: resolved } : {});
@@ -7775,6 +8121,15 @@ function WorkflowEditor({
7775
8121
  },
7776
8122
  [actions]
7777
8123
  );
8124
+ const toggleWorkflowSettings = (0, import_react24.useCallback)(() => {
8125
+ if (inspectorOpen && selectionRef.current?.kind === "workflow") {
8126
+ handleSelectionChange(null);
8127
+ } else {
8128
+ handleSelectionChange(
8129
+ activeWorkflowRef.current ? { kind: "workflow", workflow: activeWorkflowRef.current } : null
8130
+ );
8131
+ }
8132
+ }, [inspectorOpen, handleSelectionChange]);
7778
8133
  const confirmAddState = (0, import_react24.useCallback)(
7779
8134
  (name) => {
7780
8135
  const workflow = state.activeWorkflow;
@@ -7914,10 +8269,15 @@ function WorkflowEditor({
7914
8269
  if (!wf) return null;
7915
8270
  return wf.states[pendingConnect.fromState] ?? null;
7916
8271
  }, [pendingConnect, state.document]);
7917
- const orientation = layoutOptions?.orientation ?? "vertical";
8272
+ const orientation = layoutPref.orientation;
7918
8273
  const effectiveLayoutOptions = (0, import_react24.useMemo)(
7919
- () => ({ ...layoutOptions, pinned: pinnedNodes }),
7920
- [layoutOptions, pinnedNodes]
8274
+ () => ({
8275
+ ...layoutOptions,
8276
+ orientation: layoutPref.orientation,
8277
+ preset: layoutPref.preset,
8278
+ pinned: pinnedNodes
8279
+ }),
8280
+ [layoutOptions, layoutPref, pinnedNodes]
7921
8281
  );
7922
8282
  const savedViewport = state.activeWorkflow ? state.document.meta.workflowUi[state.activeWorkflow]?.viewports?.[orientation] : void 0;
7923
8283
  (0, import_react24.useEffect)(() => {
@@ -7959,13 +8319,13 @@ function WorkflowEditor({
7959
8319
  if (readOnly || anyModalOpen) return;
7960
8320
  openAddStateModal({ x, y });
7961
8321
  }, [anyModalOpen, openAddStateModal, readOnly]);
7962
- const graphPane = /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8322
+ const graphPane = /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7963
8323
  "div",
7964
8324
  {
7965
8325
  "data-testid": "workflow-editor-graph-pane",
7966
8326
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%", position: "relative" },
7967
8327
  children: [
7968
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8328
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7969
8329
  Canvas,
7970
8330
  {
7971
8331
  graph: derived.graph,
@@ -7978,6 +8338,7 @@ function WorkflowEditor({
7978
8338
  transitionPositions,
7979
8339
  onTransitionLabelDragEnd: handleTransitionLabelDragEnd,
7980
8340
  onSelectionChange: handleSelectionChange,
8341
+ onToggleWorkflowSettings: toggleWorkflowSettings,
7981
8342
  onViewportChange: handleViewportChange,
7982
8343
  onConnect: handleConnect,
7983
8344
  onReconnect: handleReconnect,
@@ -8003,6 +8364,8 @@ function WorkflowEditor({
8003
8364
  onUndo: !readOnly ? actions.undo : void 0,
8004
8365
  onRedo: !readOnly ? actions.redo : void 0,
8005
8366
  onAutoLayout: !readOnly ? handleAutoLayout : void 0,
8367
+ onSetLayoutOrientation: !readOnly ? (o) => applyLayoutPref({ orientation: o }) : void 0,
8368
+ onSetLayoutDensity: !readOnly ? (p) => applyLayoutPref({ preset: p }) : void 0,
8006
8369
  isFullscreen,
8007
8370
  onToggleFullscreen: handleToggleFullscreen,
8008
8371
  resizeKey: inspectorVisible ? 1 : 0,
@@ -8010,7 +8373,7 @@ function WorkflowEditor({
8010
8373
  helpLabel: mergedMessages.toolbar.help
8011
8374
  }
8012
8375
  ),
8013
- reconnectError && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8376
+ reconnectError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8014
8377
  "div",
8015
8378
  {
8016
8379
  role: "alert",
@@ -8035,7 +8398,7 @@ function WorkflowEditor({
8035
8398
  state.activeWorkflow && (() => {
8036
8399
  const comments = state.document.meta.workflowUi[state.activeWorkflow]?.comments;
8037
8400
  if (!comments) return null;
8038
- return Object.values(comments).map((c) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8401
+ return Object.values(comments).map((c) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8039
8402
  CommentNode,
8040
8403
  {
8041
8404
  comment: c,
@@ -8058,12 +8421,12 @@ function WorkflowEditor({
8058
8421
  ]
8059
8422
  }
8060
8423
  );
8061
- const jsonPane = enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8424
+ const jsonPane = enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8062
8425
  "div",
8063
8426
  {
8064
8427
  "data-testid": "workflow-editor-json-pane",
8065
8428
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%" },
8066
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8429
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8067
8430
  WorkflowJsonEditor,
8068
8431
  {
8069
8432
  document: state.document,
@@ -8079,7 +8442,7 @@ function WorkflowEditor({
8079
8442
  )
8080
8443
  }
8081
8444
  ) : null;
8082
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8445
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
8083
8446
  "div",
8084
8447
  {
8085
8448
  ref: editorContainerRef,
@@ -8100,7 +8463,7 @@ function WorkflowEditor({
8100
8463
  onKeyDown: handleKeyDown,
8101
8464
  tabIndex: -1,
8102
8465
  children: [
8103
- chrome?.tabs !== false && showTabs && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8466
+ chrome?.tabs !== false && showTabs && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8104
8467
  WorkflowTabs,
8105
8468
  {
8106
8469
  workflows,
@@ -8127,9 +8490,9 @@ function WorkflowEditor({
8127
8490
  onVersionChange: handleVersionChange
8128
8491
  }
8129
8492
  ),
8130
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
8131
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
8132
- (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8493
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
8494
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
8495
+ (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
8133
8496
  "div",
8134
8497
  {
8135
8498
  style: {
@@ -8143,8 +8506,8 @@ function WorkflowEditor({
8143
8506
  },
8144
8507
  "data-testid": "workflow-editor-surface-tabs",
8145
8508
  children: [
8146
- enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
8147
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8509
+ enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
8510
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8148
8511
  SurfaceTab,
8149
8512
  {
8150
8513
  active: activeSurface === "graph",
@@ -8152,7 +8515,7 @@ function WorkflowEditor({
8152
8515
  children: mergedMessages.editorView.graph
8153
8516
  }
8154
8517
  ),
8155
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8518
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8156
8519
  SurfaceTab,
8157
8520
  {
8158
8521
  active: activeSurface === "json",
@@ -8161,8 +8524,8 @@ function WorkflowEditor({
8161
8524
  }
8162
8525
  )
8163
8526
  ] }),
8164
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { flex: 1 } }),
8165
- !readOnly && activeSurface === "graph" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8527
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { flex: 1 } }),
8528
+ !readOnly && activeSurface === "graph" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
8166
8529
  "button",
8167
8530
  {
8168
8531
  type: "button",
@@ -8183,7 +8546,7 @@ function WorkflowEditor({
8183
8546
  cursor: "pointer"
8184
8547
  },
8185
8548
  children: [
8186
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M12 5v14M5 12h14" }) }),
8549
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "M12 5v14M5 12h14" }) }),
8187
8550
  mergedMessages.toolbar.addStateButton
8188
8551
  ]
8189
8552
  }
@@ -8191,7 +8554,7 @@ function WorkflowEditor({
8191
8554
  ]
8192
8555
  }
8193
8556
  ),
8194
- enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8557
+ enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
8195
8558
  "div",
8196
8559
  {
8197
8560
  style: {
@@ -8204,10 +8567,10 @@ function WorkflowEditor({
8204
8567
  "data-testid": "workflow-editor-split-view",
8205
8568
  children: [
8206
8569
  graphPane,
8207
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8570
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8208
8571
  ]
8209
8572
  }
8210
- ) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
8573
+ ) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
8211
8574
  "div",
8212
8575
  {
8213
8576
  style: {
@@ -8219,8 +8582,8 @@ function WorkflowEditor({
8219
8582
  flexDirection: "column"
8220
8583
  },
8221
8584
  children: [
8222
- graphVisible ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8223
- enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8585
+ graphVisible ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8586
+ enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8224
8587
  "div",
8225
8588
  {
8226
8589
  style: {
@@ -8237,7 +8600,7 @@ function WorkflowEditor({
8237
8600
  }
8238
8601
  )
8239
8602
  ] }),
8240
- inspectorVisible && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8603
+ inspectorVisible && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8241
8604
  InspectorFrame,
8242
8605
  {
8243
8606
  mode: placement.mode,
@@ -8247,7 +8610,7 @@ function WorkflowEditor({
8247
8610
  onDockedWidthChange: setInspectorWidth,
8248
8611
  onRestore: restoreInspector,
8249
8612
  onClose: () => handleSelectionChange(null),
8250
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8613
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8251
8614
  Inspector,
8252
8615
  {
8253
8616
  document: state.document,
@@ -8266,7 +8629,7 @@ function WorkflowEditor({
8266
8629
  }
8267
8630
  )
8268
8631
  ] }),
8269
- pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8632
+ pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8270
8633
  AddStateModal,
8271
8634
  {
8272
8635
  existingNames: Object.keys(
@@ -8278,7 +8641,7 @@ function WorkflowEditor({
8278
8641
  onCancel: () => setPendingAddState(null)
8279
8642
  }
8280
8643
  ),
8281
- pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8644
+ pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8282
8645
  DeleteStateModal,
8283
8646
  {
8284
8647
  document: state.document,
@@ -8288,7 +8651,7 @@ function WorkflowEditor({
8288
8651
  onCancel: () => setPendingDelete(null)
8289
8652
  }
8290
8653
  ),
8291
- pendingConnect && pendingConnectState && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8654
+ pendingConnect && pendingConnectState && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8292
8655
  DragConnectModal,
8293
8656
  {
8294
8657
  source: pendingConnectState,
@@ -8298,8 +8661,8 @@ function WorkflowEditor({
8298
8661
  onCancel: () => setPendingConnect(null)
8299
8662
  }
8300
8663
  ),
8301
- helpOpen && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HelpModal, { onCancel: () => setHelpOpen(false) }),
8302
- pendingVersionSwitch && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8664
+ helpOpen && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(HelpModal, { onCancel: () => setHelpOpen(false) }),
8665
+ pendingVersionSwitch && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8303
8666
  VersionSwitchModal,
8304
8667
  {
8305
8668
  fromVersion: `v${state.document.meta.cyodaVersion ?? import_workflow_core11.LATEST_CYODA_VERSION}`,
@@ -8312,8 +8675,8 @@ function WorkflowEditor({
8312
8675
  onCancel: () => setPendingVersionSwitch(null)
8313
8676
  }
8314
8677
  ),
8315
- chrome?.toolbar !== false && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { position: "relative" }, children: [
8316
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8678
+ chrome?.toolbar !== false && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { position: "relative" }, children: [
8679
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8317
8680
  Toolbar,
8318
8681
  {
8319
8682
  derived,
@@ -8328,7 +8691,7 @@ function WorkflowEditor({
8328
8691
  toolbarEnd
8329
8692
  }
8330
8693
  ),
8331
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8694
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8332
8695
  IssuesDrawer,
8333
8696
  {
8334
8697
  open: openIssueSeverity !== null,
@@ -8400,7 +8763,10 @@ function buildReconnectTransaction(doc, edge, connection) {
8400
8763
  summary: `Reconnect transition "${transition.name}"`,
8401
8764
  patches: patches2,
8402
8765
  inverses: inverses2,
8403
- selectionAfter: { kind: "transition", transitionUuid: edge.id }
8766
+ // A pure re-anchor is a layout tweak — preserve the current selection
8767
+ // (omitting selectionAfter). Changing the target state is a structural
8768
+ // edit, so select the transition.
8769
+ ...targetChanged ? { selectionAfter: { kind: "transition", transitionUuid: edge.id } } : {}
8404
8770
  }
8405
8771
  };
8406
8772
  }
@@ -8508,7 +8874,7 @@ function SurfaceTab({
8508
8874
  onClick,
8509
8875
  children
8510
8876
  }) {
8511
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8877
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8512
8878
  "button",
8513
8879
  {
8514
8880
  type: "button",
@@ -8639,7 +9005,7 @@ function useSaveFlow(args) {
8639
9005
 
8640
9006
  // src/save/SaveConfirmModal.tsx
8641
9007
  var import_react26 = require("react");
8642
- var import_jsx_runtime29 = require("react/jsx-runtime");
9008
+ var import_jsx_runtime30 = require("react/jsx-runtime");
8643
9009
  function SaveConfirmModal({
8644
9010
  mode,
8645
9011
  requiresExplicitConfirm,
@@ -8652,14 +9018,14 @@ function SaveConfirmModal({
8652
9018
  const [ackMode, setAckMode] = (0, import_react26.useState)(!requiresExplicitConfirm);
8653
9019
  const [ackWarnings, setAckWarnings] = (0, import_react26.useState)(warningCount === 0);
8654
9020
  const blocked = !ackMode || !ackWarnings;
8655
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(ModalFrame, { onCancel, children: [
8656
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
8657
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
9021
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(ModalFrame, { onCancel, children: [
9022
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
9023
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
8658
9024
  messages.saveConfirm.modeLabel,
8659
9025
  ": ",
8660
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("strong", { children: mode })
9026
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("strong", { children: mode })
8661
9027
  ] }),
8662
- diffSummary2 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
9028
+ diffSummary2 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8663
9029
  "pre",
8664
9030
  {
8665
9031
  style: {
@@ -8678,8 +9044,8 @@ function SaveConfirmModal({
8678
9044
  children: diffSummary2
8679
9045
  }
8680
9046
  ),
8681
- requiresExplicitConfirm && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8682
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
9047
+ requiresExplicitConfirm && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
9048
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8683
9049
  "input",
8684
9050
  {
8685
9051
  type: "checkbox",
@@ -8687,10 +9053,10 @@ function SaveConfirmModal({
8687
9053
  onChange: (e) => setAckMode(e.target.checked)
8688
9054
  }
8689
9055
  ),
8690
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
9056
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8691
9057
  ] }),
8692
- warningCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8693
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
9058
+ warningCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
9059
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8694
9060
  "input",
8695
9061
  {
8696
9062
  type: "checkbox",
@@ -8698,11 +9064,11 @@ function SaveConfirmModal({
8698
9064
  onChange: (e) => setAckWarnings(e.target.checked)
8699
9065
  }
8700
9066
  ),
8701
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
9067
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8702
9068
  ] }),
8703
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
8704
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
8705
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
9069
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
9070
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
9071
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8706
9072
  "button",
8707
9073
  {
8708
9074
  type: "button",
@@ -8740,10 +9106,10 @@ var primaryBtn5 = {
8740
9106
  };
8741
9107
 
8742
9108
  // src/save/ConflictBanner.tsx
8743
- var import_jsx_runtime30 = require("react/jsx-runtime");
9109
+ var import_jsx_runtime31 = require("react/jsx-runtime");
8744
9110
  function ConflictBanner({ onReload, onForceOverwrite }) {
8745
9111
  const messages = useMessages();
8746
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
9112
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
8747
9113
  "div",
8748
9114
  {
8749
9115
  style: {
@@ -8759,8 +9125,8 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8759
9125
  role: "alert",
8760
9126
  "data-testid": "conflict-banner",
8761
9127
  children: [
8762
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { flex: 1 }, children: messages.conflict.message }),
8763
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
9128
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { style: { flex: 1 }, children: messages.conflict.message }),
9129
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
8764
9130
  "button",
8765
9131
  {
8766
9132
  type: "button",
@@ -8770,7 +9136,7 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8770
9136
  children: messages.conflict.reload
8771
9137
  }
8772
9138
  ),
8773
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
9139
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
8774
9140
  "button",
8775
9141
  {
8776
9142
  type: "button",