@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.js CHANGED
@@ -11,6 +11,49 @@ import {
11
11
  } from "@cyoda/workflow-core";
12
12
  import { estimateNodeSize as estimateNodeSize2 } from "@cyoda/workflow-layout";
13
13
 
14
+ // src/components/layoutPref.ts
15
+ var DENSITY_OPTIONS = [
16
+ { value: "websiteCompact", label: "Compact" },
17
+ { value: "opsAudit", label: "Comfortable" },
18
+ { value: "configuratorReadable", label: "Roomy" }
19
+ ];
20
+ var KNOWN_PRESETS = new Set(
21
+ DENSITY_OPTIONS.map((d) => d.value)
22
+ );
23
+ function defaultLayoutPref(opts) {
24
+ return {
25
+ orientation: opts?.orientation === "horizontal" ? "horizontal" : "vertical",
26
+ preset: opts?.preset && KNOWN_PRESETS.has(opts.preset) ? opts.preset : "configuratorReadable"
27
+ };
28
+ }
29
+ function prefKey(base) {
30
+ return base === null ? null : `${base}:pref`;
31
+ }
32
+ function loadLayoutPref(base, opts) {
33
+ const fallback = defaultLayoutPref(opts);
34
+ const key = prefKey(base);
35
+ if (key === null || typeof localStorage === "undefined") return fallback;
36
+ try {
37
+ const raw = localStorage.getItem(key);
38
+ if (!raw) return fallback;
39
+ const parsed = JSON.parse(raw);
40
+ return {
41
+ orientation: parsed.orientation === "horizontal" ? "horizontal" : "vertical",
42
+ preset: typeof parsed.preset === "string" && KNOWN_PRESETS.has(parsed.preset) ? parsed.preset : fallback.preset
43
+ };
44
+ } catch {
45
+ return fallback;
46
+ }
47
+ }
48
+ function saveLayoutPref(base, pref) {
49
+ const key = prefKey(base);
50
+ if (key === null || typeof localStorage === "undefined") return;
51
+ try {
52
+ localStorage.setItem(key, JSON.stringify(pref));
53
+ } catch {
54
+ }
55
+ }
56
+
14
57
  // src/i18n/context.ts
15
58
  import { createContext, useContext } from "react";
16
59
 
@@ -37,8 +80,6 @@ var defaultMessages = {
37
80
  statesTitle: "States",
38
81
  stateInitial: "Initial \u2014 workflow entry point",
39
82
  stateDefault: "Regular state",
40
- stateProcessing: "Processing \u2014 automated work",
41
- stateManualReview: "Manual review \u2014 needs a person",
42
83
  stateTerminal: "Terminal \u2014 workflow ends here",
43
84
  stateError: "Red border \u2014 validation error",
44
85
  stateWarning: "Amber border \u2014 validation warning",
@@ -182,6 +223,8 @@ var defaultMessages = {
182
223
  noneManual: "No criterion. This manual transition is available whenever the entity is in this state.",
183
224
  noneAutomated: "No criterion. This automated transition will fire as soon as the entity reaches this state.",
184
225
  noneAutomatedWarning: "Automated transitions without criteria should usually be last in the transition order.",
226
+ workflowCaption: "Determines whether this workflow applies to an entity of its model \u2014 set one to disambiguate when several workflows target the same model.",
227
+ workflowNone: "No workflow criterion set.",
185
228
  cancel: "Cancel",
186
229
  applyModal: "Apply",
187
230
  revert: "Revert",
@@ -229,8 +272,6 @@ function summarize(patch) {
229
272
  return `Rename workflow "${patch.from}" \u2192 "${patch.to}"`;
230
273
  case "setInitialState":
231
274
  return `Set initial state to "${patch.stateCode}"`;
232
- case "setWorkflowCriterion":
233
- return patch.criterion ? `Set workflow criterion` : `Clear workflow criterion`;
234
275
  case "addState":
235
276
  return `Add state "${patch.stateCode}"`;
236
277
  case "renameState":
@@ -255,8 +296,10 @@ function summarize(patch) {
255
296
  return `Remove processor`;
256
297
  case "reorderProcessor":
257
298
  return `Reorder processor`;
258
- case "setCriterion":
259
- return patch.criterion ? `Set criterion` : `Clear criterion`;
299
+ case "setCriterion": {
300
+ const scope = patch.host.kind === "workflow" ? "workflow criterion" : "criterion";
301
+ return patch.criterion ? `Set ${scope}` : `Clear ${scope}`;
302
+ }
260
303
  case "setAnnotations":
261
304
  return patch.annotations ? `Set annotations` : `Clear annotations`;
262
305
  case "setImportMode":
@@ -501,20 +544,120 @@ import {
501
544
  import "reactflow/dist/style.css";
502
545
  import { layoutGraph, estimateNodeSize } from "@cyoda/workflow-layout";
503
546
 
547
+ // src/components/LayoutOptionsMenu.tsx
548
+ import { jsx, jsxs } from "react/jsx-runtime";
549
+ var ORIENTATION_OPTIONS = [
550
+ { value: "vertical", label: "Vertical" },
551
+ { value: "horizontal", label: "Horizontal" }
552
+ ];
553
+ function LayoutOptionsMenu({
554
+ orientation,
555
+ density,
556
+ onSetOrientation,
557
+ onSetDensity
558
+ }) {
559
+ return /* @__PURE__ */ jsxs("div", { style: panelStyle, "data-testid": "layout-options-menu", role: "group", "aria-label": "Auto-layout options", children: [
560
+ /* @__PURE__ */ jsx("div", { style: labelStyle, children: "Orientation" }),
561
+ /* @__PURE__ */ jsx(
562
+ Segmented,
563
+ {
564
+ options: ORIENTATION_OPTIONS,
565
+ value: orientation,
566
+ onChange: onSetOrientation,
567
+ testIdPrefix: "layout-orientation"
568
+ }
569
+ ),
570
+ /* @__PURE__ */ jsx("div", { style: labelStyle, children: "Density" }),
571
+ /* @__PURE__ */ jsx(
572
+ Segmented,
573
+ {
574
+ options: DENSITY_OPTIONS,
575
+ value: density,
576
+ onChange: onSetDensity,
577
+ testIdPrefix: "layout-density"
578
+ }
579
+ )
580
+ ] });
581
+ }
582
+ function Segmented({
583
+ options,
584
+ value,
585
+ onChange,
586
+ testIdPrefix
587
+ }) {
588
+ return /* @__PURE__ */ jsx("div", { style: segmentedStyle, children: options.map((opt) => {
589
+ const active = opt.value === value;
590
+ return /* @__PURE__ */ jsx(
591
+ "button",
592
+ {
593
+ type: "button",
594
+ onClick: () => onChange(opt.value),
595
+ "aria-pressed": active,
596
+ "data-testid": `${testIdPrefix}-${opt.value}`,
597
+ style: active ? segActiveStyle : segStyle,
598
+ children: opt.label
599
+ },
600
+ opt.value
601
+ );
602
+ }) });
603
+ }
604
+ var panelStyle = {
605
+ display: "flex",
606
+ flexDirection: "column",
607
+ gap: 6,
608
+ padding: 10,
609
+ width: 210,
610
+ background: "white",
611
+ border: "1px solid #D1D5DB",
612
+ borderRadius: 8,
613
+ boxShadow: "0 4px 16px rgba(15,23,42,0.14)"
614
+ };
615
+ var labelStyle = {
616
+ fontSize: 11,
617
+ fontWeight: 600,
618
+ letterSpacing: "0.04em",
619
+ color: "#64748B"
620
+ };
621
+ var segmentedStyle = {
622
+ display: "flex",
623
+ gap: 3,
624
+ padding: 3,
625
+ background: "#F1F5F9",
626
+ border: "1px solid #E2E8F0",
627
+ borderRadius: 7
628
+ };
629
+ var segStyle = {
630
+ flex: 1,
631
+ border: "none",
632
+ background: "transparent",
633
+ color: "#475569",
634
+ fontSize: 12,
635
+ fontWeight: 550,
636
+ padding: "5px 4px",
637
+ borderRadius: 5,
638
+ cursor: "pointer"
639
+ };
640
+ var segActiveStyle = {
641
+ ...segStyle,
642
+ background: "#2E63D6",
643
+ color: "white",
644
+ boxShadow: "0 1px 2px rgba(15,23,42,0.18)"
645
+ };
646
+
504
647
  // src/components/ArrowMarkers.tsx
505
648
  import { geometry, workflowPalette } from "@cyoda/workflow-viewer/theme";
506
- import { jsx } from "react/jsx-runtime";
649
+ import { jsx as jsx2 } from "react/jsx-runtime";
507
650
  function ArrowMarkers() {
508
651
  const size = geometry.edge.arrowheadSize;
509
652
  const colors2 = Array.from(new Set(Object.values(workflowPalette.edge)));
510
- return /* @__PURE__ */ jsx(
653
+ return /* @__PURE__ */ jsx2(
511
654
  "svg",
512
655
  {
513
656
  width: 0,
514
657
  height: 0,
515
658
  style: { position: "absolute", pointerEvents: "none" },
516
659
  "aria-hidden": true,
517
- children: /* @__PURE__ */ jsx("defs", { children: colors2.map((color) => /* @__PURE__ */ jsx(
660
+ children: /* @__PURE__ */ jsx2("defs", { children: colors2.map((color) => /* @__PURE__ */ jsx2(
518
661
  "marker",
519
662
  {
520
663
  id: arrowMarkerId(color),
@@ -524,7 +667,7 @@ function ArrowMarkers() {
524
667
  markerWidth: size,
525
668
  markerHeight: size,
526
669
  orient: "auto-start-reverse",
527
- children: /* @__PURE__ */ jsx(
670
+ children: /* @__PURE__ */ jsx2(
528
671
  "path",
529
672
  {
530
673
  d: `M 0 ${size / 2} L ${size * 2} ${size} L 0 ${size * 1.5} z`,
@@ -580,7 +723,7 @@ import {
580
723
  typography,
581
724
  workflowPalette as workflowPalette2
582
725
  } from "@cyoda/workflow-viewer/theme";
583
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
726
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
584
727
  function StateRoleIcon({ label, color }) {
585
728
  const common = {
586
729
  width: 10,
@@ -593,24 +736,12 @@ function StateRoleIcon({ label, color }) {
593
736
  "aria-hidden": true
594
737
  };
595
738
  if (label === "INITIAL") {
596
- return /* @__PURE__ */ jsx2("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ jsx2("polygon", { points: "2.5,1.5 8.5,5 2.5,8.5", fill: color, stroke: "none" }) });
739
+ return /* @__PURE__ */ jsx3("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ jsx3("polygon", { points: "2.5,1.5 8.5,5 2.5,8.5", fill: color, stroke: "none" }) });
597
740
  }
598
741
  if (label === "TERMINAL") {
599
- return /* @__PURE__ */ jsx2("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ jsx2("rect", { x: "1.8", y: "1.8", width: "6.4", height: "6.4", rx: "1", fill: color, stroke: "none" }) });
600
- }
601
- if (label === "MANUAL REVIEW") {
602
- return /* @__PURE__ */ jsxs("svg", { ...common, viewBox: "0 0 10 10", children: [
603
- /* @__PURE__ */ jsx2("path", { d: "M5 2.2 L7 5 L5 7.8 L3 5 Z" }),
604
- /* @__PURE__ */ jsx2("circle", { cx: "5", cy: "5", r: "0.8", fill: color, stroke: "none" })
605
- ] });
606
- }
607
- if (label === "PROCESSING" || label === "PROCESSING STATE") {
608
- return /* @__PURE__ */ jsxs("svg", { ...common, viewBox: "0 0 10 10", children: [
609
- /* @__PURE__ */ jsx2("circle", { cx: "5", cy: "5", r: "2.6" }),
610
- /* @__PURE__ */ jsx2("path", { d: "M5 1.4 V2.7 M5 7.3 V8.6 M1.4 5 H2.7 M7.3 5 H8.6" })
611
- ] });
742
+ return /* @__PURE__ */ jsx3("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ jsx3("rect", { x: "1.8", y: "1.8", width: "6.4", height: "6.4", rx: "1", fill: color, stroke: "none" }) });
612
743
  }
613
- return /* @__PURE__ */ jsx2("svg", { ...common, viewBox: "0 0 10 10", children: /* @__PURE__ */ jsx2("circle", { cx: "5", cy: "5", r: "2.2", fill: color, stroke: "none" }) });
744
+ return null;
614
745
  }
615
746
  function RfStateNodeImpl({ data, selected, id }) {
616
747
  const { node, hasError, hasWarning, size } = data;
@@ -624,7 +755,7 @@ function RfStateNodeImpl({ data, selected, id }) {
624
755
  const [showAnchors, setShowAnchors] = useState2(false);
625
756
  const borderColor = hasError ? "#DC2626" : hasWarning ? "#D97706" : selected ? workflowPalette2.neutrals.slate900 : palette.border;
626
757
  const borderWidth = selected ? strokeWidth + 1 : strokeWidth;
627
- return /* @__PURE__ */ jsxs(
758
+ return /* @__PURE__ */ jsxs2(
628
759
  "div",
629
760
  {
630
761
  style: {
@@ -638,11 +769,11 @@ function RfStateNodeImpl({ data, selected, id }) {
638
769
  transition: "opacity 0.15s ease"
639
770
  },
640
771
  "data-testid": `rf-state-${node.stateCode}`,
641
- "aria-label": `${category} state: ${node.stateCode}`,
772
+ "aria-label": category ? `${category} state: ${node.stateCode}` : `state: ${node.stateCode}`,
642
773
  onMouseEnter: () => setShowAnchors(true),
643
774
  onMouseLeave: () => setShowAnchors(false),
644
775
  children: [
645
- ALL_ANCHORS.map(({ side, position, inset }) => /* @__PURE__ */ jsx2(
776
+ ALL_ANCHORS.map(({ side, position, inset }) => /* @__PURE__ */ jsx3(
646
777
  AnchorHandle,
647
778
  {
648
779
  side,
@@ -653,7 +784,7 @@ function RfStateNodeImpl({ data, selected, id }) {
653
784
  },
654
785
  side
655
786
  )),
656
- /* @__PURE__ */ jsxs(
787
+ /* @__PURE__ */ jsxs2(
657
788
  "div",
658
789
  {
659
790
  style: {
@@ -673,7 +804,7 @@ function RfStateNodeImpl({ data, selected, id }) {
673
804
  padding: "0 8px"
674
805
  },
675
806
  children: [
676
- /* @__PURE__ */ jsxs(
807
+ category && /* @__PURE__ */ jsxs2(
677
808
  "div",
678
809
  {
679
810
  style: {
@@ -690,12 +821,12 @@ function RfStateNodeImpl({ data, selected, id }) {
690
821
  },
691
822
  "data-testid": `rf-state-${node.stateCode}-category`,
692
823
  children: [
693
- /* @__PURE__ */ jsx2(StateRoleIcon, { label: category, color: palette.meta }),
824
+ /* @__PURE__ */ jsx3(StateRoleIcon, { label: category, color: palette.meta }),
694
825
  category
695
826
  ]
696
827
  }
697
828
  ),
698
- /* @__PURE__ */ jsx2(
829
+ /* @__PURE__ */ jsx3(
699
830
  "div",
700
831
  {
701
832
  style: {
@@ -794,8 +925,8 @@ function AnchorHandle({
794
925
  transition: "opacity 120ms ease",
795
926
  ...geo.dotOffset
796
927
  };
797
- return /* @__PURE__ */ jsxs(Fragment, { children: [
798
- /* @__PURE__ */ jsx2(
928
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
929
+ /* @__PURE__ */ jsx3(
799
930
  Handle,
800
931
  {
801
932
  id: side,
@@ -804,7 +935,7 @@ function AnchorHandle({
804
935
  style: handleStyle
805
936
  }
806
937
  ),
807
- /* @__PURE__ */ jsx2(
938
+ /* @__PURE__ */ jsx3(
808
939
  Handle,
809
940
  {
810
941
  id: side,
@@ -813,7 +944,7 @@ function AnchorHandle({
813
944
  style: handleStyle
814
945
  }
815
946
  ),
816
- /* @__PURE__ */ jsx2("div", { style: dotStyle })
947
+ /* @__PURE__ */ jsx3("div", { style: dotStyle })
817
948
  ] });
818
949
  }
819
950
  function visibleHandleStyle(position, offset, isSplit, active) {
@@ -1220,10 +1351,11 @@ function midpoint(points) {
1220
1351
  }
1221
1352
 
1222
1353
  // src/components/TransitionTooltip.tsx
1354
+ import { AnnotationLines } from "@cyoda/workflow-viewer";
1223
1355
  import { typography as typography2, workflowPalette as workflowPalette3 } from "@cyoda/workflow-viewer/theme";
1224
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1356
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1225
1357
  function TransitionTooltip({ transition, x, y }) {
1226
- return /* @__PURE__ */ jsxs2(
1358
+ return /* @__PURE__ */ jsxs3(
1227
1359
  "div",
1228
1360
  {
1229
1361
  style: {
@@ -1244,61 +1376,66 @@ function TransitionTooltip({ transition, x, y }) {
1244
1376
  pointerEvents: "none"
1245
1377
  },
1246
1378
  children: [
1247
- /* @__PURE__ */ jsx3("div", { style: { fontWeight: 700, fontSize: 11, letterSpacing: "0.06em", marginBottom: 8, color: workflowPalette3.neutrals.slate500, textTransform: "uppercase" }, children: transition.name }),
1248
- transition.criterion && /* @__PURE__ */ jsxs2("section", { style: { marginBottom: transition.processors?.length ? 8 : 0 }, children: [
1249
- /* @__PURE__ */ jsx3(Label, { children: "Criterion" }),
1250
- /* @__PURE__ */ jsx3(CriterionView, { criterion: transition.criterion })
1379
+ /* @__PURE__ */ jsx4("div", { style: { fontWeight: 700, fontSize: 11, letterSpacing: "0.06em", marginBottom: 8, color: workflowPalette3.neutrals.slate500, textTransform: "uppercase" }, children: transition.name }),
1380
+ /* @__PURE__ */ jsx4(AnnotationLines, { annotations: transition.annotations }),
1381
+ (transition.criterion || transition.criterionAnnotations) && /* @__PURE__ */ jsxs3("section", { style: { marginBottom: transition.processors?.length ? 8 : 0 }, children: [
1382
+ /* @__PURE__ */ jsx4(Label, { children: "Criterion" }),
1383
+ /* @__PURE__ */ jsx4(AnnotationLines, { annotations: transition.criterionAnnotations }),
1384
+ transition.criterion && /* @__PURE__ */ jsx4(CriterionView, { criterion: transition.criterion })
1251
1385
  ] }),
1252
- !!transition.processors?.length && /* @__PURE__ */ jsxs2("section", { children: [
1253
- /* @__PURE__ */ jsx3(Label, { children: "Processors" }),
1254
- transition.processors.map((p, i) => /* @__PURE__ */ jsx3(ProcessorView, { processor: p }, i))
1386
+ !!transition.processors?.length && /* @__PURE__ */ jsxs3("section", { children: [
1387
+ /* @__PURE__ */ jsx4(Label, { children: "Processors" }),
1388
+ transition.processors.map((p, i) => /* @__PURE__ */ jsx4(ProcessorView, { processor: p }, i))
1255
1389
  ] }),
1256
- !transition.criterion && !transition.processors?.length && /* @__PURE__ */ jsx3("div", { style: { color: workflowPalette3.neutrals.slate500, fontStyle: "italic" }, children: "No criterion or processors" })
1390
+ !transition.criterion && !transition.criterionAnnotations && !transition.processors?.length && /* @__PURE__ */ jsx4("div", { style: { color: workflowPalette3.neutrals.slate500, fontStyle: "italic" }, children: "No criterion or processors" })
1257
1391
  ]
1258
1392
  }
1259
1393
  );
1260
1394
  }
1261
1395
  function Label({ children }) {
1262
- return /* @__PURE__ */ jsx3("div", { style: { fontWeight: 600, fontSize: 10, letterSpacing: "0.05em", color: workflowPalette3.neutrals.slate500, textTransform: "uppercase", marginBottom: 4 }, children });
1396
+ return /* @__PURE__ */ jsx4("div", { style: { fontWeight: 600, fontSize: 10, letterSpacing: "0.05em", color: workflowPalette3.neutrals.slate500, textTransform: "uppercase", marginBottom: 4 }, children });
1263
1397
  }
1264
1398
  function CriterionView({ criterion, depth = 0 }) {
1265
1399
  const indent = depth * 12;
1266
1400
  const s = { paddingLeft: indent, marginBottom: 3 };
1267
- if (criterion.type === "simple") return /* @__PURE__ */ jsxs2("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1268
- /* @__PURE__ */ jsx3(Chip, { color: "blue", children: criterion.operation }),
1269
- /* @__PURE__ */ jsx3("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath }),
1270
- criterion.value !== void 0 && /* @__PURE__ */ jsxs2("span", { style: { marginLeft: 4, color: workflowPalette3.neutrals.slate500 }, children: [
1401
+ if (criterion.type === "simple") return /* @__PURE__ */ jsxs3("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1402
+ /* @__PURE__ */ jsx4(Chip, { color: "blue", children: criterion.operation }),
1403
+ /* @__PURE__ */ jsx4("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath }),
1404
+ criterion.value !== void 0 && /* @__PURE__ */ jsxs3("span", { style: { marginLeft: 4, color: workflowPalette3.neutrals.slate500 }, children: [
1271
1405
  "= ",
1272
1406
  JSON.stringify(criterion.value)
1273
1407
  ] })
1274
1408
  ] });
1275
- if (criterion.type === "lifecycle") return /* @__PURE__ */ jsxs2("div", { style: s, children: [
1276
- /* @__PURE__ */ jsx3(Chip, { color: "purple", children: criterion.field }),
1277
- /* @__PURE__ */ jsx3(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1278
- criterion.value !== void 0 && /* @__PURE__ */ jsx3("span", { style: { marginLeft: 4, color: workflowPalette3.neutrals.slate500 }, children: JSON.stringify(criterion.value) })
1409
+ if (criterion.type === "lifecycle") return /* @__PURE__ */ jsxs3("div", { style: s, children: [
1410
+ /* @__PURE__ */ jsx4(Chip, { color: "purple", children: criterion.field }),
1411
+ /* @__PURE__ */ jsx4(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1412
+ criterion.value !== void 0 && /* @__PURE__ */ jsx4("span", { style: { marginLeft: 4, color: workflowPalette3.neutrals.slate500 }, children: JSON.stringify(criterion.value) })
1279
1413
  ] });
1280
- if (criterion.type === "function") return /* @__PURE__ */ jsxs2("div", { style: s, children: [
1281
- /* @__PURE__ */ jsx3(Chip, { color: "green", children: "fn" }),
1282
- /* @__PURE__ */ jsx3("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.function.name }),
1283
- criterion.function.criterion && /* @__PURE__ */ jsx3(CriterionView, { criterion: criterion.function.criterion, depth: depth + 1 })
1414
+ if (criterion.type === "function") return /* @__PURE__ */ jsxs3("div", { style: s, children: [
1415
+ /* @__PURE__ */ jsx4(Chip, { color: "green", children: "fn" }),
1416
+ /* @__PURE__ */ jsx4("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.function.name }),
1417
+ criterion.function.criterion && /* @__PURE__ */ jsx4(CriterionView, { criterion: criterion.function.criterion, depth: depth + 1 })
1284
1418
  ] });
1285
- if (criterion.type === "array") return /* @__PURE__ */ jsxs2("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1286
- /* @__PURE__ */ jsx3(Chip, { color: "orange", children: "array" }),
1287
- /* @__PURE__ */ jsx3(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1288
- /* @__PURE__ */ jsx3("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath })
1419
+ if (criterion.type === "array") return /* @__PURE__ */ jsxs3("div", { style: { ...s, overflowWrap: "break-word" }, children: [
1420
+ /* @__PURE__ */ jsx4(Chip, { color: "orange", children: "array" }),
1421
+ /* @__PURE__ */ jsx4(Chip, { color: "blue", style: { marginLeft: 4 }, children: criterion.operation }),
1422
+ /* @__PURE__ */ jsx4("code", { style: { fontSize: 11, marginLeft: 4 }, children: criterion.jsonPath })
1289
1423
  ] });
1290
- if (criterion.type === "group") return /* @__PURE__ */ jsxs2("div", { style: s, children: [
1291
- /* @__PURE__ */ jsx3(Chip, { color: "slate", children: criterion.operator }),
1292
- /* @__PURE__ */ jsx3("div", { style: { marginTop: 3 }, children: criterion.conditions.map((c, i) => /* @__PURE__ */ jsx3(CriterionView, { criterion: c, depth: depth + 1 }, i)) })
1424
+ if (criterion.type === "group") return /* @__PURE__ */ jsxs3("div", { style: s, children: [
1425
+ /* @__PURE__ */ jsx4(Chip, { color: "slate", children: criterion.operator }),
1426
+ /* @__PURE__ */ jsx4("div", { style: { marginTop: 3 }, children: criterion.conditions.map((c, i) => /* @__PURE__ */ jsx4(CriterionView, { criterion: c, depth: depth + 1 }, i)) })
1293
1427
  ] });
1294
1428
  return null;
1295
1429
  }
1296
1430
  function ProcessorView({ processor }) {
1297
1431
  const mode = processor.executionMode ?? "ASYNC_NEW_TX";
1298
- return /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 4, display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1299
- /* @__PURE__ */ jsx3("code", { style: { fontSize: 11, fontWeight: 600 }, children: processor.name }),
1300
- mode !== "ASYNC_NEW_TX" && /* @__PURE__ */ jsx3(Chip, { color: "blue", children: mode.replace(/_/g, " ") }),
1301
- processor.config?.calculationNodesTags && /* @__PURE__ */ jsx3(Chip, { color: "slate", children: processor.config.calculationNodesTags })
1432
+ return /* @__PURE__ */ jsxs3("div", { style: { marginBottom: 4 }, children: [
1433
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1434
+ /* @__PURE__ */ jsx4("code", { style: { fontSize: 11, fontWeight: 600 }, children: processor.name }),
1435
+ mode !== "ASYNC_NEW_TX" && /* @__PURE__ */ jsx4(Chip, { color: "blue", children: mode.replace(/_/g, " ") }),
1436
+ processor.config?.calculationNodesTags && /* @__PURE__ */ jsx4(Chip, { color: "slate", children: processor.config.calculationNodesTags })
1437
+ ] }),
1438
+ /* @__PURE__ */ jsx4(AnnotationLines, { annotations: processor.annotations })
1302
1439
  ] });
1303
1440
  }
1304
1441
  function Chip({ children, color, style }) {
@@ -1310,11 +1447,11 @@ function Chip({ children, color, style }) {
1310
1447
  slate: { bg: "#F1F5F9", text: "#475569" }
1311
1448
  };
1312
1449
  const { bg, text } = palette[color] ?? palette["slate"];
1313
- return /* @__PURE__ */ jsx3("span", { style: { background: bg, color: text, borderRadius: 3, padding: "1px 5px", fontSize: 10, fontWeight: 600, letterSpacing: "0.03em", ...style }, children });
1450
+ return /* @__PURE__ */ jsx4("span", { style: { background: bg, color: text, borderRadius: 3, padding: "1px 5px", fontSize: 10, fontWeight: 600, letterSpacing: "0.03em", ...style }, children });
1314
1451
  }
1315
1452
 
1316
1453
  // src/components/RfTransitionEdge.tsx
1317
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1454
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1318
1455
  function RfTransitionEdgeImpl(props) {
1319
1456
  const {
1320
1457
  id,
@@ -1363,8 +1500,8 @@ function RfTransitionEdgeImpl(props) {
1363
1500
  manual: edge.manual,
1364
1501
  disabled: edge.disabled
1365
1502
  });
1366
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
1367
- /* @__PURE__ */ jsx4(
1503
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1504
+ /* @__PURE__ */ jsx5(
1368
1505
  BaseEdge,
1369
1506
  {
1370
1507
  id,
@@ -1379,7 +1516,7 @@ function RfTransitionEdgeImpl(props) {
1379
1516
  markerEnd: `url(#${arrowMarkerId(color)})`
1380
1517
  }
1381
1518
  ),
1382
- /* @__PURE__ */ jsx4(EdgeLabelRenderer, { children: /* @__PURE__ */ jsxs3(
1519
+ /* @__PURE__ */ jsx5(EdgeLabelRenderer, { children: /* @__PURE__ */ jsxs4(
1383
1520
  "div",
1384
1521
  {
1385
1522
  style: {
@@ -1462,7 +1599,7 @@ function RfTransitionEdgeImpl(props) {
1462
1599
  }
1463
1600
  } : void 0,
1464
1601
  children: [
1465
- /* @__PURE__ */ jsx4(
1602
+ /* @__PURE__ */ jsx5(
1466
1603
  "div",
1467
1604
  {
1468
1605
  style: {
@@ -1475,9 +1612,9 @@ function RfTransitionEdgeImpl(props) {
1475
1612
  children: edge.summary.display
1476
1613
  }
1477
1614
  ),
1478
- badges.length > 0 && /* @__PURE__ */ jsx4("div", { style: { display: "flex", gap: 3, flexWrap: "wrap", justifyContent: "center" }, children: badges.map((b, i) => {
1615
+ badges.length > 0 && /* @__PURE__ */ jsx5("div", { style: { display: "flex", gap: 3, flexWrap: "wrap", justifyContent: "center" }, children: badges.map((b, i) => {
1479
1616
  const slot = b.key === "manual" ? workflowPalette4.badge.manual : b.key === "processor" || b.key === "execution" ? workflowPalette4.badge.processor : b.key === "criterion" ? workflowPalette4.badge.criterion : workflowPalette4.badge.disabled;
1480
- return /* @__PURE__ */ jsx4(
1617
+ return /* @__PURE__ */ jsx5(
1481
1618
  "span",
1482
1619
  {
1483
1620
  style: {
@@ -1499,7 +1636,7 @@ function RfTransitionEdgeImpl(props) {
1499
1636
  }
1500
1637
  ) }),
1501
1638
  tooltipPos && data.transition && createPortal(
1502
- /* @__PURE__ */ jsx4(TransitionTooltip, { transition: data.transition, x: tooltipPos.x, y: tooltipPos.y }),
1639
+ /* @__PURE__ */ jsx5(TransitionTooltip, { transition: data.transition, x: tooltipPos.x, y: tooltipPos.y }),
1503
1640
  document.body
1504
1641
  )
1505
1642
  ] });
@@ -1539,7 +1676,7 @@ function findNonOverlappingCenter(desiredCenter, size, obstacles, options = {})
1539
1676
 
1540
1677
  // src/components/Canvas.tsx
1541
1678
  import { badgesFor as badgesFor2 } from "@cyoda/workflow-viewer/theme";
1542
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1679
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1543
1680
  var nodeTypes = { stateNode: RfStateNode };
1544
1681
  var edgeTypes = { transition: RfTransitionEdge };
1545
1682
  function toRfNodes(graph, layout, activeWorkflow, issuesByNode, selection) {
@@ -2408,6 +2545,7 @@ function CanvasInner({
2408
2545
  issues,
2409
2546
  activeWorkflow,
2410
2547
  selection,
2548
+ onToggleWorkflowSettings,
2411
2549
  layoutOptions,
2412
2550
  savedViewport,
2413
2551
  onSelectionChange,
@@ -2419,6 +2557,8 @@ function CanvasInner({
2419
2557
  onNodeDragStop,
2420
2558
  onPaneDoubleClick,
2421
2559
  newStatePositionRef,
2560
+ onSetLayoutOrientation,
2561
+ onSetLayoutDensity,
2422
2562
  layoutKey = 0,
2423
2563
  readOnly,
2424
2564
  showMinimap = true,
@@ -2437,6 +2577,7 @@ function CanvasInner({
2437
2577
  onTransitionLabelDragEnd
2438
2578
  }) {
2439
2579
  const [layout, setLayout] = useState4(null);
2580
+ const [layoutMenuOpen, setLayoutMenuOpen] = useState4(false);
2440
2581
  const [nodes, setNodes] = useState4([]);
2441
2582
  const [hoveredId, setHoveredId] = useState4(null);
2442
2583
  const previousBasePositionsRef = useRef3(null);
@@ -2613,6 +2754,7 @@ function CanvasInner({
2613
2754
  const onEdgeMouseEnter = useCallback2((_, edge) => setHoveredId(edge.id), []);
2614
2755
  const onEdgeMouseLeave = useCallback2(() => setHoveredId(null), []);
2615
2756
  const onNodeClick = (_, node) => {
2757
+ if (isReconnectingRef.current) return;
2616
2758
  const data = node.data;
2617
2759
  onSelectionChange({
2618
2760
  kind: "state",
@@ -2689,7 +2831,7 @@ function CanvasInner({
2689
2831
  newStatePositionRef.current = null;
2690
2832
  };
2691
2833
  }, [newStatePositionRef, computeNewStatePosition]);
2692
- return /* @__PURE__ */ jsx5(HoverContext.Provider, { value: { highlightSet }, children: /* @__PURE__ */ jsxs4(
2834
+ return /* @__PURE__ */ jsx6(HoverContext.Provider, { value: { highlightSet }, children: /* @__PURE__ */ jsxs5(
2693
2835
  "div",
2694
2836
  {
2695
2837
  ref: wrapperRef,
@@ -2697,8 +2839,8 @@ function CanvasInner({
2697
2839
  "data-testid": "workflow-canvas",
2698
2840
  onDoubleClick: readOnly ? void 0 : handleCanvasDoubleClick,
2699
2841
  children: [
2700
- /* @__PURE__ */ jsx5(ArrowMarkers, {}),
2701
- showControls && /* @__PURE__ */ jsxs4(
2842
+ /* @__PURE__ */ jsx6(ArrowMarkers, {}),
2843
+ showControls && /* @__PURE__ */ jsxs5(
2702
2844
  "div",
2703
2845
  {
2704
2846
  className: "nodrag nopan",
@@ -2716,12 +2858,12 @@ function CanvasInner({
2716
2858
  overflow: "hidden"
2717
2859
  },
2718
2860
  children: [
2719
- !readOnly && onUndo && /* @__PURE__ */ jsxs4(Fragment3, { children: [
2720
- /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onUndo, disabled: !canUndo, title: "Undo (Ctrl+Z)", testId: "canvas-undo", children: /* @__PURE__ */ jsx5(UndoIcon, {}) }),
2721
- /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onRedo, disabled: !canRedo, title: "Redo (Ctrl+Shift+Z)", testId: "canvas-redo", children: /* @__PURE__ */ jsx5(RedoIcon, {}) }),
2722
- /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } })
2861
+ !readOnly && onUndo && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2862
+ /* @__PURE__ */ jsx6(CtrlBtn, { onClick: onUndo, disabled: !canUndo, title: "Undo (Ctrl+Z)", testId: "canvas-undo", children: /* @__PURE__ */ jsx6(UndoIcon, {}) }),
2863
+ /* @__PURE__ */ jsx6(CtrlBtn, { onClick: onRedo, disabled: !canRedo, title: "Redo (Ctrl+Shift+Z)", testId: "canvas-redo", children: /* @__PURE__ */ jsx6(RedoIcon, {}) }),
2864
+ /* @__PURE__ */ jsx6("div", { style: { height: 1, background: "#E2E8F0" } })
2723
2865
  ] }),
2724
- /* @__PURE__ */ jsx5(
2866
+ /* @__PURE__ */ jsx6(
2725
2867
  CtrlBtn,
2726
2868
  {
2727
2869
  onClick: () => {
@@ -2731,32 +2873,60 @@ function CanvasInner({
2731
2873
  });
2732
2874
  },
2733
2875
  title: "Fit view",
2734
- children: /* @__PURE__ */ jsx5(FitViewIcon, {})
2876
+ children: /* @__PURE__ */ jsx6(FitViewIcon, {})
2735
2877
  }
2736
2878
  ),
2737
- /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onToggleFullscreen, title: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: isFullscreen ? /* @__PURE__ */ jsx5(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx5(EnterFullscreenIcon, {}) }),
2738
- !readOnly && onAutoLayout && /* @__PURE__ */ jsxs4(Fragment3, { children: [
2739
- /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } }),
2740
- /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onAutoLayout, title: "Auto-arrange (L)", testId: "canvas-auto-layout", children: /* @__PURE__ */ jsx5(AutoArrangeIcon, {}) })
2879
+ /* @__PURE__ */ jsx6(CtrlBtn, { onClick: onToggleFullscreen, title: isFullscreen ? "Exit fullscreen" : "Fullscreen", children: isFullscreen ? /* @__PURE__ */ jsx6(ExitFullscreenIcon, {}) : /* @__PURE__ */ jsx6(EnterFullscreenIcon, {}) }),
2880
+ !readOnly && onAutoLayout && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2881
+ /* @__PURE__ */ jsx6("div", { style: { height: 1, background: "#E2E8F0" } }),
2882
+ /* @__PURE__ */ jsx6(CtrlBtn, { onClick: onAutoLayout, title: "Auto-arrange (L)", testId: "canvas-auto-layout", children: /* @__PURE__ */ jsx6(AutoArrangeIcon, {}) }),
2883
+ onSetLayoutOrientation && onSetLayoutDensity && /* @__PURE__ */ jsx6(
2884
+ CtrlBtn,
2885
+ {
2886
+ onClick: () => setLayoutMenuOpen((v) => !v),
2887
+ title: "Layout options",
2888
+ testId: "canvas-layout-options",
2889
+ children: /* @__PURE__ */ jsx6(LayoutOptionsIcon, {})
2890
+ }
2891
+ )
2741
2892
  ] }),
2742
- onHelp && /* @__PURE__ */ jsxs4(Fragment3, { children: [
2743
- /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } }),
2744
- /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ jsx5(HelpIcon, {}) })
2893
+ onHelp && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2894
+ /* @__PURE__ */ jsx6("div", { style: { height: 1, background: "#E2E8F0" } }),
2895
+ /* @__PURE__ */ jsx6(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ jsx6(HelpIcon, {}) })
2745
2896
  ] }),
2746
- /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } }),
2747
- /* @__PURE__ */ jsx5(
2897
+ /* @__PURE__ */ jsx6("div", { style: { height: 1, background: "#E2E8F0" } }),
2898
+ /* @__PURE__ */ jsx6(
2748
2899
  CtrlBtn,
2749
2900
  {
2750
- onClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2901
+ onClick: onToggleWorkflowSettings ?? (() => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null)),
2751
2902
  title: "Workflow settings",
2752
2903
  testId: "canvas-workflow-settings",
2753
- children: /* @__PURE__ */ jsx5(WorkflowSettingsIcon, {})
2904
+ children: /* @__PURE__ */ jsx6(WorkflowSettingsIcon, {})
2754
2905
  }
2755
2906
  )
2756
2907
  ]
2757
2908
  }
2758
2909
  ),
2759
- /* @__PURE__ */ jsxs4(
2910
+ layoutMenuOpen && onSetLayoutOrientation && onSetLayoutDensity && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2911
+ /* @__PURE__ */ jsx6(
2912
+ "div",
2913
+ {
2914
+ onClick: () => setLayoutMenuOpen(false),
2915
+ style: { position: "absolute", inset: 0, zIndex: 6 },
2916
+ "data-testid": "layout-options-backdrop"
2917
+ }
2918
+ ),
2919
+ /* @__PURE__ */ jsx6("div", { className: "nodrag nopan", style: { position: "absolute", bottom: 16, left: 64, zIndex: 7 }, children: /* @__PURE__ */ jsx6(
2920
+ LayoutOptionsMenu,
2921
+ {
2922
+ orientation,
2923
+ density: preset,
2924
+ onSetOrientation: onSetLayoutOrientation,
2925
+ onSetDensity: onSetLayoutDensity
2926
+ }
2927
+ ) })
2928
+ ] }),
2929
+ /* @__PURE__ */ jsxs5(
2760
2930
  ReactFlow,
2761
2931
  {
2762
2932
  nodes,
@@ -2766,14 +2936,19 @@ function CanvasInner({
2766
2936
  onNodesChange: readOnly ? void 0 : handleNodesChange,
2767
2937
  onNodeClick,
2768
2938
  onEdgeClick,
2769
- onPaneClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2939
+ onPaneClick: () => {
2940
+ if (isReconnectingRef.current) return;
2941
+ onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null);
2942
+ },
2770
2943
  onConnect: readOnly ? void 0 : onConnect,
2771
2944
  onReconnect: readOnly ? void 0 : onReconnect,
2772
2945
  onReconnectStart: readOnly ? void 0 : () => {
2773
2946
  isReconnectingRef.current = true;
2774
2947
  },
2775
2948
  onReconnectEnd: readOnly ? void 0 : () => {
2776
- isReconnectingRef.current = false;
2949
+ setTimeout(() => {
2950
+ isReconnectingRef.current = false;
2951
+ }, 0);
2777
2952
  },
2778
2953
  onNodesDelete: readOnly ? void 0 : onNodesDelete,
2779
2954
  onEdgesDelete: readOnly ? void 0 : onEdgesDelete,
@@ -2799,8 +2974,8 @@ function CanvasInner({
2799
2974
  if (layout) onViewportChange?.(viewport);
2800
2975
  },
2801
2976
  children: [
2802
- /* @__PURE__ */ jsx5(Background, {}),
2803
- showMinimap && /* @__PURE__ */ jsx5(MiniMap, { zoomable: true, pannable: true })
2977
+ /* @__PURE__ */ jsx6(Background, {}),
2978
+ showMinimap && /* @__PURE__ */ jsx6(MiniMap, { zoomable: true, pannable: true })
2804
2979
  ]
2805
2980
  }
2806
2981
  )
@@ -2815,7 +2990,7 @@ function CtrlBtn({
2815
2990
  testId,
2816
2991
  children
2817
2992
  }) {
2818
- return /* @__PURE__ */ jsx5(
2993
+ return /* @__PURE__ */ jsx6(
2819
2994
  "button",
2820
2995
  {
2821
2996
  type: "button",
@@ -2840,50 +3015,58 @@ function CtrlBtn({
2840
3015
  );
2841
3016
  }
2842
3017
  function FitViewIcon() {
2843
- return /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("path", { d: "M3 7V4h3M18 4h3v3M21 17v3h-3M6 20H3v-3" }) });
3018
+ return /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M3 7V4h3M18 4h3v3M21 17v3h-3M6 20H3v-3" }) });
2844
3019
  }
2845
3020
  function UndoIcon() {
2846
- return /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("path", { d: "M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" }) });
3021
+ return /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" }) });
2847
3022
  }
2848
3023
  function RedoIcon() {
2849
- return /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("path", { d: "M15 15l6-6m0 0-6-6m6 6H9a6 6 0 0 0 0 12h3" }) });
3024
+ return /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "M15 15l6-6m0 0-6-6m6 6H9a6 6 0 0 0 0 12h3" }) });
2850
3025
  }
2851
3026
  function EnterFullscreenIcon() {
2852
- return /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("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" }) });
3027
+ return /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("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" }) });
2853
3028
  }
2854
3029
  function ExitFullscreenIcon() {
2855
- return /* @__PURE__ */ jsx5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx5("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" }) });
3030
+ return /* @__PURE__ */ jsx6("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("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" }) });
2856
3031
  }
2857
3032
  function AutoArrangeIcon() {
2858
- return /* @__PURE__ */ jsxs4("svg", { width: "14", height: "14", viewBox: "0 0 22 20", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
2859
- /* @__PURE__ */ jsx5("rect", { x: "6", y: "0", width: "10", height: "5", rx: "1.5" }),
2860
- /* @__PURE__ */ jsx5("line", { x1: "11", y1: "5", x2: "11", y2: "9" }),
2861
- /* @__PURE__ */ jsx5("line", { x1: "4", y1: "9", x2: "18", y2: "9" }),
2862
- /* @__PURE__ */ jsx5("line", { x1: "4", y1: "9", x2: "4", y2: "12" }),
2863
- /* @__PURE__ */ jsx5("line", { x1: "18", y1: "9", x2: "18", y2: "12" }),
2864
- /* @__PURE__ */ jsx5("rect", { x: "0", y: "12", width: "8", height: "5", rx: "1.5" }),
2865
- /* @__PURE__ */ jsx5("rect", { x: "14", y: "12", width: "8", height: "5", rx: "1.5" })
3033
+ return /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 22 20", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
3034
+ /* @__PURE__ */ jsx6("rect", { x: "6", y: "0", width: "10", height: "5", rx: "1.5" }),
3035
+ /* @__PURE__ */ jsx6("line", { x1: "11", y1: "5", x2: "11", y2: "9" }),
3036
+ /* @__PURE__ */ jsx6("line", { x1: "4", y1: "9", x2: "18", y2: "9" }),
3037
+ /* @__PURE__ */ jsx6("line", { x1: "4", y1: "9", x2: "4", y2: "12" }),
3038
+ /* @__PURE__ */ jsx6("line", { x1: "18", y1: "9", x2: "18", y2: "12" }),
3039
+ /* @__PURE__ */ jsx6("rect", { x: "0", y: "12", width: "8", height: "5", rx: "1.5" }),
3040
+ /* @__PURE__ */ jsx6("rect", { x: "14", y: "12", width: "8", height: "5", rx: "1.5" })
2866
3041
  ] });
2867
3042
  }
2868
3043
  function HelpIcon() {
2869
- return /* @__PURE__ */ jsxs4("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2870
- /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "10" }),
2871
- /* @__PURE__ */ jsx5("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
2872
- /* @__PURE__ */ jsx5("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
3044
+ return /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3045
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10" }),
3046
+ /* @__PURE__ */ jsx6("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
3047
+ /* @__PURE__ */ jsx6("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
3048
+ ] });
3049
+ }
3050
+ function LayoutOptionsIcon() {
3051
+ return /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 22 22", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", children: [
3052
+ /* @__PURE__ */ jsx6("line", { x1: "3", y1: "7", x2: "19", y2: "7" }),
3053
+ /* @__PURE__ */ jsx6("line", { x1: "3", y1: "15", x2: "19", y2: "15" }),
3054
+ /* @__PURE__ */ jsx6("circle", { cx: "8", cy: "7", r: "2.4", fill: "white" }),
3055
+ /* @__PURE__ */ jsx6("circle", { cx: "14", cy: "15", r: "2.4", fill: "white" })
2873
3056
  ] });
2874
3057
  }
2875
3058
  function WorkflowSettingsIcon() {
2876
- return /* @__PURE__ */ jsxs4("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2877
- /* @__PURE__ */ jsx5("line", { x1: "4", y1: "6", x2: "20", y2: "6" }),
2878
- /* @__PURE__ */ jsx5("line", { x1: "4", y1: "12", x2: "20", y2: "12" }),
2879
- /* @__PURE__ */ jsx5("line", { x1: "4", y1: "18", x2: "20", y2: "18" }),
2880
- /* @__PURE__ */ jsx5("circle", { cx: "9", cy: "6", r: "2", fill: "white" }),
2881
- /* @__PURE__ */ jsx5("circle", { cx: "15", cy: "12", r: "2", fill: "white" }),
2882
- /* @__PURE__ */ jsx5("circle", { cx: "8", cy: "18", r: "2", fill: "white" })
3059
+ return /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3060
+ /* @__PURE__ */ jsx6("line", { x1: "4", y1: "6", x2: "20", y2: "6" }),
3061
+ /* @__PURE__ */ jsx6("line", { x1: "4", y1: "12", x2: "20", y2: "12" }),
3062
+ /* @__PURE__ */ jsx6("line", { x1: "4", y1: "18", x2: "20", y2: "18" }),
3063
+ /* @__PURE__ */ jsx6("circle", { cx: "9", cy: "6", r: "2", fill: "white" }),
3064
+ /* @__PURE__ */ jsx6("circle", { cx: "15", cy: "12", r: "2", fill: "white" }),
3065
+ /* @__PURE__ */ jsx6("circle", { cx: "8", cy: "18", r: "2", fill: "white" })
2883
3066
  ] });
2884
3067
  }
2885
3068
  function Canvas(props) {
2886
- return /* @__PURE__ */ jsx5(ReactFlowProvider, { children: /* @__PURE__ */ jsx5(CanvasInner, { ...props }) });
3069
+ return /* @__PURE__ */ jsx6(ReactFlowProvider, { children: /* @__PURE__ */ jsx6(CanvasInner, { ...props }) });
2887
3070
  }
2888
3071
 
2889
3072
  // src/components/resolveConnection.ts
@@ -3062,7 +3245,7 @@ function resolveSelection(doc, selection) {
3062
3245
 
3063
3246
  // src/inspector/fields.tsx
3064
3247
  import { useEffect as useEffect2, useRef as useRef4, useState as useState5 } from "react";
3065
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
3248
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3066
3249
  function TextField({
3067
3250
  label,
3068
3251
  value,
@@ -3080,9 +3263,9 @@ function TextField({
3080
3263
  syncedKeyRef.current = syncKey;
3081
3264
  setDraft(value);
3082
3265
  }
3083
- return /* @__PURE__ */ jsxs5("label", { style: rowStyle, children: [
3084
- /* @__PURE__ */ jsx6("span", { style: labelStyle, children: label }),
3085
- multiline ? /* @__PURE__ */ jsx6(
3266
+ return /* @__PURE__ */ jsxs6("label", { style: rowStyle, children: [
3267
+ /* @__PURE__ */ jsx7("span", { style: labelStyle2, children: label }),
3268
+ multiline ? /* @__PURE__ */ jsx7(
3086
3269
  "textarea",
3087
3270
  {
3088
3271
  value: draft,
@@ -3096,7 +3279,7 @@ function TextField({
3096
3279
  },
3097
3280
  style: { ...inputStyle, resize: "vertical", lineHeight: 1.5 }
3098
3281
  }
3099
- ) : /* @__PURE__ */ jsx6(
3282
+ ) : /* @__PURE__ */ jsx7(
3100
3283
  "input",
3101
3284
  {
3102
3285
  type: "text",
@@ -3123,8 +3306,8 @@ function CheckboxField({
3123
3306
  disabled,
3124
3307
  testId
3125
3308
  }) {
3126
- return /* @__PURE__ */ jsxs5("label", { style: { ...rowStyle, flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3127
- /* @__PURE__ */ jsx6(
3309
+ return /* @__PURE__ */ jsxs6("label", { style: { ...rowStyle, flexDirection: "row", alignItems: "center", gap: 8 }, children: [
3310
+ /* @__PURE__ */ jsx7(
3128
3311
  "input",
3129
3312
  {
3130
3313
  type: "checkbox",
@@ -3134,7 +3317,7 @@ function CheckboxField({
3134
3317
  "data-testid": testId
3135
3318
  }
3136
3319
  ),
3137
- /* @__PURE__ */ jsx6("span", { style: { ...labelStyle, marginBottom: 0 }, children: label })
3320
+ /* @__PURE__ */ jsx7("span", { style: { ...labelStyle2, marginBottom: 0 }, children: label })
3138
3321
  ] });
3139
3322
  }
3140
3323
  function SelectField({
@@ -3145,9 +3328,9 @@ function SelectField({
3145
3328
  disabled,
3146
3329
  testId
3147
3330
  }) {
3148
- return /* @__PURE__ */ jsxs5("label", { style: rowStyle, children: [
3149
- /* @__PURE__ */ jsx6("span", { style: labelStyle, children: label }),
3150
- /* @__PURE__ */ jsx6(
3331
+ return /* @__PURE__ */ jsxs6("label", { style: rowStyle, children: [
3332
+ /* @__PURE__ */ jsx7("span", { style: labelStyle2, children: label }),
3333
+ /* @__PURE__ */ jsx7(
3151
3334
  CustomSelectInput,
3152
3335
  {
3153
3336
  value,
@@ -3225,8 +3408,8 @@ function CustomSelectInput({
3225
3408
  setHighlightedIndex((i) => Math.max(i - 1, 0));
3226
3409
  }
3227
3410
  };
3228
- return /* @__PURE__ */ jsxs5("div", { ref: containerRef, style: { position: "relative" }, children: [
3229
- /* @__PURE__ */ jsxs5(
3411
+ return /* @__PURE__ */ jsxs6("div", { ref: containerRef, style: { position: "relative" }, children: [
3412
+ /* @__PURE__ */ jsxs6(
3230
3413
  "select",
3231
3414
  {
3232
3415
  value,
@@ -3237,12 +3420,12 @@ function CustomSelectInput({
3237
3420
  "aria-hidden": "true",
3238
3421
  tabIndex: -1,
3239
3422
  children: [
3240
- disabledOption && /* @__PURE__ */ jsx6("option", { value: disabledOption.value, disabled: true, children: disabledOption.label }),
3241
- groups ? groups.map((g) => /* @__PURE__ */ jsx6("optgroup", { label: g.groupLabel, children: g.options.map((o) => /* @__PURE__ */ jsx6("option", { value: o.value, children: o.label }, o.value)) }, g.groupLabel)) : flatOptions.map((o) => /* @__PURE__ */ jsx6("option", { value: o.value, children: o.label }, o.value))
3423
+ disabledOption && /* @__PURE__ */ jsx7("option", { value: disabledOption.value, disabled: true, children: disabledOption.label }),
3424
+ groups ? groups.map((g) => /* @__PURE__ */ jsx7("optgroup", { label: g.groupLabel, children: g.options.map((o) => /* @__PURE__ */ jsx7("option", { value: o.value, children: o.label }, o.value)) }, g.groupLabel)) : flatOptions.map((o) => /* @__PURE__ */ jsx7("option", { value: o.value, children: o.label }, o.value))
3242
3425
  ]
3243
3426
  }
3244
3427
  ),
3245
- /* @__PURE__ */ jsx6(
3428
+ /* @__PURE__ */ jsx7(
3246
3429
  "div",
3247
3430
  {
3248
3431
  role: "combobox",
@@ -3259,7 +3442,7 @@ function CustomSelectInput({
3259
3442
  children: selectedLabel
3260
3443
  }
3261
3444
  ),
3262
- open && /* @__PURE__ */ jsx6(
3445
+ open && /* @__PURE__ */ jsx7(
3263
3446
  "div",
3264
3447
  {
3265
3448
  role: "listbox",
@@ -3279,7 +3462,7 @@ function CustomSelectInput({
3279
3462
  overflowY: "auto"
3280
3463
  },
3281
3464
  children: renderItems.map(
3282
- (item, i) => item.kind === "header" ? /* @__PURE__ */ jsx6(
3465
+ (item, i) => item.kind === "header" ? /* @__PURE__ */ jsx7(
3283
3466
  "div",
3284
3467
  {
3285
3468
  style: {
@@ -3295,7 +3478,7 @@ function CustomSelectInput({
3295
3478
  children: item.label
3296
3479
  },
3297
3480
  `header-${item.label}`
3298
- ) : /* @__PURE__ */ jsx6(
3481
+ ) : /* @__PURE__ */ jsx7(
3299
3482
  "div",
3300
3483
  {
3301
3484
  role: "option",
@@ -3324,8 +3507,8 @@ function CustomSelectInput({
3324
3507
  ] });
3325
3508
  }
3326
3509
  function FieldGroup({ title, children }) {
3327
- return /* @__PURE__ */ jsxs5("section", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
3328
- /* @__PURE__ */ jsx6("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
3510
+ return /* @__PURE__ */ jsxs6("section", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
3511
+ /* @__PURE__ */ jsx7("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
3329
3512
  children
3330
3513
  ] });
3331
3514
  }
@@ -3334,7 +3517,7 @@ var rowStyle = {
3334
3517
  flexDirection: "column",
3335
3518
  gap: 4
3336
3519
  };
3337
- var labelStyle = {
3520
+ var labelStyle2 = {
3338
3521
  fontSize: 12,
3339
3522
  color: colors.textSecondary,
3340
3523
  marginBottom: 2
@@ -3397,7 +3580,7 @@ function installMonacoCancellationFilter() {
3397
3580
  installMonacoCancellationFilter();
3398
3581
 
3399
3582
  // src/inspector/JsonMonacoField.tsx
3400
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3583
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3401
3584
  function reformat(text) {
3402
3585
  try {
3403
3586
  return JSON.stringify(JSON.parse(text), null, 2);
@@ -3412,8 +3595,8 @@ function JsonMonacoField(props) {
3412
3595
  const next = reformat(props.buffer);
3413
3596
  if (next !== null && next !== props.buffer) props.onChange(next);
3414
3597
  };
3415
- return /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
3416
- /* @__PURE__ */ jsx7("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ jsx7(
3598
+ return /* @__PURE__ */ jsxs7("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
3599
+ /* @__PURE__ */ jsx8("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ jsx8(
3417
3600
  "button",
3418
3601
  {
3419
3602
  type: "button",
@@ -3424,7 +3607,7 @@ function JsonMonacoField(props) {
3424
3607
  children: messages.inspector.format
3425
3608
  }
3426
3609
  ) }),
3427
- monaco ? /* @__PURE__ */ jsx7(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ jsx7(
3610
+ monaco ? /* @__PURE__ */ jsx8(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ jsx8(
3428
3611
  "textarea",
3429
3612
  {
3430
3613
  value: props.buffer,
@@ -3507,7 +3690,7 @@ function MonacoPane({
3507
3690
  useEffect3(() => {
3508
3691
  editorRef.current?.updateOptions?.({ readOnly: disabled });
3509
3692
  }, [disabled]);
3510
- return /* @__PURE__ */ jsx7(
3693
+ return /* @__PURE__ */ jsx8(
3511
3694
  "div",
3512
3695
  {
3513
3696
  ref: containerRef,
@@ -3549,14 +3732,14 @@ function parseAnnotationsJson(text) {
3549
3732
  }
3550
3733
 
3551
3734
  // src/inspector/AnnotationsField.tsx
3552
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3735
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3553
3736
  var pretty = (v) => JSON.stringify(v, null, 2);
3554
3737
  function AnnotationsField(props) {
3555
3738
  const messages = useMessages();
3556
3739
  if (props.value === void 0) {
3557
- return /* @__PURE__ */ jsxs7("div", { style: sectionStyle, children: [
3558
- props.showLabel !== false && /* @__PURE__ */ jsx8(SectionLabel, {}),
3559
- !props.disabled && /* @__PURE__ */ jsx8(
3740
+ return /* @__PURE__ */ jsxs8("div", { style: sectionStyle, children: [
3741
+ props.showLabel !== false && /* @__PURE__ */ jsx9(SectionLabel, {}),
3742
+ !props.disabled && /* @__PURE__ */ jsx9(
3560
3743
  "button",
3561
3744
  {
3562
3745
  type: "button",
@@ -3568,7 +3751,7 @@ function AnnotationsField(props) {
3568
3751
  )
3569
3752
  ] });
3570
3753
  }
3571
- return /* @__PURE__ */ jsx8(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3754
+ return /* @__PURE__ */ jsx9(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3572
3755
  }
3573
3756
  function AnnotationsEditor({
3574
3757
  value,
@@ -3608,9 +3791,9 @@ function AnnotationsEditor({
3608
3791
  setBuffer(pretty(value));
3609
3792
  setDocChanged(false);
3610
3793
  };
3611
- return /* @__PURE__ */ jsxs7("div", { style: sectionStyle, children: [
3612
- showLabel !== false && /* @__PURE__ */ jsx8(SectionLabel, {}),
3613
- /* @__PURE__ */ jsx8(
3794
+ return /* @__PURE__ */ jsxs8("div", { style: sectionStyle, children: [
3795
+ showLabel !== false && /* @__PURE__ */ jsx9(SectionLabel, {}),
3796
+ /* @__PURE__ */ jsx9(
3614
3797
  JsonMonacoField,
3615
3798
  {
3616
3799
  buffer,
@@ -3621,10 +3804,10 @@ function AnnotationsEditor({
3621
3804
  testId: "annotations-json-editor"
3622
3805
  }
3623
3806
  ),
3624
- result.error && /* @__PURE__ */ jsx8("div", { role: "alert", "data-testid": "annotations-error", style: errorStyle, children: result.error }),
3625
- docChanged && /* @__PURE__ */ jsx8("div", { role: "alert", "data-testid": "annotations-doc-changed", style: warnStyle, children: messages.inspector.annotationsDocChanged }),
3626
- !disabled && /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3627
- /* @__PURE__ */ jsx8(
3807
+ result.error && /* @__PURE__ */ jsx9("div", { role: "alert", "data-testid": "annotations-error", style: errorStyle, children: result.error }),
3808
+ docChanged && /* @__PURE__ */ jsx9("div", { role: "alert", "data-testid": "annotations-doc-changed", style: warnStyle, children: messages.inspector.annotationsDocChanged }),
3809
+ !disabled && /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3810
+ /* @__PURE__ */ jsx9(
3628
3811
  "button",
3629
3812
  {
3630
3813
  type: "button",
@@ -3635,14 +3818,14 @@ function AnnotationsEditor({
3635
3818
  children: messages.inspector.annotationsApply
3636
3819
  }
3637
3820
  ),
3638
- /* @__PURE__ */ jsx8("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtn, "data-testid": "inspector-annotations-revert", children: messages.inspector.annotationsRevert }),
3639
- /* @__PURE__ */ jsx8("button", { type: "button", onClick: onRemove, style: dangerBtn, "data-testid": "inspector-annotations-remove", children: messages.inspector.annotationsRemove })
3821
+ /* @__PURE__ */ jsx9("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtn, "data-testid": "inspector-annotations-revert", children: messages.inspector.annotationsRevert }),
3822
+ /* @__PURE__ */ jsx9("button", { type: "button", onClick: onRemove, style: dangerBtn, "data-testid": "inspector-annotations-remove", children: messages.inspector.annotationsRemove })
3640
3823
  ] })
3641
3824
  ] });
3642
3825
  }
3643
3826
  function SectionLabel() {
3644
3827
  const messages = useMessages();
3645
- return /* @__PURE__ */ jsx8("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: messages.inspector.annotations });
3828
+ return /* @__PURE__ */ jsx9("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: messages.inspector.annotations });
3646
3829
  }
3647
3830
  var sectionStyle = { display: "flex", flexDirection: "column", gap: 8 };
3648
3831
  var ghostBtn = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
@@ -3652,16 +3835,232 @@ var dangerBtn = { ...ghostBtn, background: colors.dangerBg, borderColor: colors.
3652
3835
  var errorStyle = { color: colors.danger, fontSize: 11 };
3653
3836
  var warnStyle = { color: colors.warning, fontSize: 11 };
3654
3837
 
3838
+ // src/inspector/CriterionField.tsx
3839
+ import { useEffect as useEffect5, useRef as useRef7, useState as useState7 } from "react";
3840
+ import { registerCriterionSchema } from "@cyoda/workflow-monaco";
3841
+
3842
+ // src/inspector/criterionJson.ts
3843
+ import { CriterionSchema, criterionBlockingError } from "@cyoda/workflow-core";
3844
+ function criterionModelUri(key) {
3845
+ return `cyoda://criterion/${key}.json`;
3846
+ }
3847
+ function zodMessage(error) {
3848
+ const first = error.issues[0];
3849
+ if (!first) return "Invalid criterion.";
3850
+ const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3851
+ return `${first.message}${path}`;
3852
+ }
3853
+ function parseCriterionJson(text) {
3854
+ let raw;
3855
+ try {
3856
+ raw = JSON.parse(text);
3857
+ } catch {
3858
+ return { criterion: null, error: "Invalid JSON." };
3859
+ }
3860
+ const res = CriterionSchema.safeParse(raw);
3861
+ if (res.success) {
3862
+ const blocking = criterionBlockingError(res.data);
3863
+ if (blocking) return { criterion: null, error: blocking };
3864
+ return { criterion: res.data, error: null };
3865
+ }
3866
+ let friendly = null;
3867
+ if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3868
+ try {
3869
+ friendly = criterionBlockingError(raw);
3870
+ } catch {
3871
+ friendly = null;
3872
+ }
3873
+ }
3874
+ return { criterion: null, error: friendly ?? zodMessage(res.error) };
3875
+ }
3876
+
3877
+ // src/inspector/CriterionField.tsx
3878
+ import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3879
+ function defaultSimpleCriterion() {
3880
+ return { type: "simple", jsonPath: "", operation: "EQUALS" };
3881
+ }
3882
+ var pretty2 = (c) => JSON.stringify(c, null, 2);
3883
+ function CriterionField(props) {
3884
+ const m = useMessages().criterion;
3885
+ if (props.value === void 0) {
3886
+ const emptyText = props.emptyText ?? (props.manual ? m.noneManual : m.noneAutomated);
3887
+ const showWarning = props.emptyText === void 0 && !props.manual;
3888
+ return /* @__PURE__ */ jsxs9("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3889
+ /* @__PURE__ */ jsx10("p", { style: summaryTextStyle, children: emptyText }),
3890
+ showWarning && /* @__PURE__ */ jsx10("p", { style: warnStyle2, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3891
+ !props.disabled && /* @__PURE__ */ jsx10("button", { type: "button", style: primaryBtnStyle, "data-testid": "inspector-criterion-add", onClick: () => props.onCommit(defaultSimpleCriterion()), children: m.add })
3892
+ ] });
3893
+ }
3894
+ return /* @__PURE__ */ jsx10(CriterionEditor, { ...props, value: props.value }, props.modelKey);
3895
+ }
3896
+ function CriterionEditor({ value, disabled, modelKey, onCommit, onRemove }) {
3897
+ const messages = useMessages();
3898
+ const m = messages.criterion;
3899
+ const [expanded, setExpanded] = useState7(false);
3900
+ const [buffer, setBuffer] = useState7(() => pretty2(value));
3901
+ const [docChanged, setDocChanged] = useState7(false);
3902
+ const prevValueRef = useRef7(value);
3903
+ useEffect5(() => {
3904
+ if (sameJson(prevValueRef.current, value)) return;
3905
+ const parsed = parseCriterionJson(buffer).criterion;
3906
+ if (parsed !== null && sameJson(parsed, value)) {
3907
+ setDocChanged(false);
3908
+ } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3909
+ setBuffer(pretty2(value));
3910
+ setDocChanged(false);
3911
+ } else {
3912
+ setDocChanged(true);
3913
+ }
3914
+ prevValueRef.current = value;
3915
+ }, [value, buffer]);
3916
+ const result = parseCriterionJson(buffer);
3917
+ const dirty = result.criterion !== null && !sameJson(result.criterion, value);
3918
+ const applyEnabled = !disabled && result.criterion !== null && dirty;
3919
+ const canRevert = buffer !== pretty2(value);
3920
+ const apply = () => {
3921
+ if (!applyEnabled || result.criterion === null) return;
3922
+ onCommit(result.criterion);
3923
+ setDocChanged(false);
3924
+ setExpanded(false);
3925
+ };
3926
+ const revert = () => {
3927
+ setBuffer(pretty2(value));
3928
+ setDocChanged(false);
3929
+ };
3930
+ return /* @__PURE__ */ jsxs9("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3931
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3932
+ /* @__PURE__ */ jsx10("span", { style: metaChipStyle, children: value.type }),
3933
+ /* @__PURE__ */ jsx10("span", { style: { flex: 1 } }),
3934
+ !disabled && !expanded && /* @__PURE__ */ jsx10("button", { type: "button", style: ghostBtnStyle, "data-testid": "inspector-criterion-edit", onClick: () => setExpanded(true), children: m.edit }),
3935
+ !disabled && /* @__PURE__ */ jsx10("button", { type: "button", style: destructiveBtnStyle, "data-testid": "inspector-criterion-remove", onClick: onRemove, children: m.remove })
3936
+ ] }),
3937
+ !expanded && /* @__PURE__ */ jsx10(CompactJson, { criterion: value }),
3938
+ expanded && /* @__PURE__ */ jsxs9(Fragment4, { children: [
3939
+ /* @__PURE__ */ jsx10(
3940
+ JsonMonacoField,
3941
+ {
3942
+ buffer,
3943
+ disabled,
3944
+ modelUri: criterionModelUri(modelKey),
3945
+ onChange: setBuffer,
3946
+ seed: buffer,
3947
+ registerSchema: registerCriterionSchema,
3948
+ testId: "criterion-json-editor"
3949
+ }
3950
+ ),
3951
+ result.error && /* @__PURE__ */ jsx10("div", { role: "alert", "data-testid": "criterion-error", style: errorStyle2, children: result.error }),
3952
+ docChanged && /* @__PURE__ */ jsx10("div", { role: "alert", "data-testid": "criterion-doc-changed", style: warnLineStyle, children: messages.inspector.annotationsDocChanged }),
3953
+ !disabled && /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3954
+ /* @__PURE__ */ jsx10("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 }),
3955
+ /* @__PURE__ */ jsx10("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtnStyle, "data-testid": "inspector-criterion-revert", children: m.revert }),
3956
+ /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => setExpanded(false), style: ghostBtnStyle, "data-testid": "inspector-criterion-collapse", children: m.collapse })
3957
+ ] })
3958
+ ] })
3959
+ ] });
3960
+ }
3961
+ function CompactJson({ criterion }) {
3962
+ const text = JSON.stringify(criterion);
3963
+ const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
3964
+ return /* @__PURE__ */ jsx10("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 });
3965
+ }
3966
+ var cardStyle = { display: "flex", flexDirection: "column", gap: 8, padding: 10, border: `1px solid ${colors.border}`, borderRadius: radii.md, background: colors.surface };
3967
+ var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
3968
+ var warnStyle2 = { margin: 0, padding: "6px 8px", background: colors.warningBg, border: `1px solid ${colors.warningBorder}`, borderRadius: radii.sm, color: colors.warning, fontSize: 11 };
3969
+ var errorStyle2 = { color: colors.danger, fontSize: 11 };
3970
+ var warnLineStyle = { color: colors.warning, fontSize: 11 };
3971
+
3972
+ // src/inspector/CriterionForm.tsx
3973
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3974
+ function criterionModelKey(host) {
3975
+ if (host.kind === "transition") return `transition-${host.transitionUuid}`;
3976
+ if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
3977
+ return `host-${host.workflow}`;
3978
+ }
3979
+ function criterionAnnotationsTarget(host) {
3980
+ if (host.kind === "workflow") return { kind: "workflowCriterion", workflow: host.workflow };
3981
+ if (host.kind === "transition") return { kind: "transitionCriterion", transitionUuid: host.transitionUuid };
3982
+ return void 0;
3983
+ }
3984
+ function CriterionSection({
3985
+ host,
3986
+ manual,
3987
+ criterion,
3988
+ criterionAnnotations,
3989
+ disabled,
3990
+ onDispatch,
3991
+ onSelectionChange: _onSelectionChange
3992
+ }) {
3993
+ const m = useMessages().criterion;
3994
+ const isWorkflow = host.kind === "workflow";
3995
+ const path = ["criterion"];
3996
+ const annotationsTarget = criterionAnnotationsTarget(host);
3997
+ return /* @__PURE__ */ jsxs10(Fragment5, { children: [
3998
+ isWorkflow && /* @__PURE__ */ jsx11(
3999
+ "p",
4000
+ {
4001
+ "data-testid": "workflow-criterion-caption",
4002
+ style: { margin: "0 0 6px", fontSize: 12, lineHeight: 1.4, color: colors.textSecondary },
4003
+ children: m.workflowCaption
4004
+ }
4005
+ ),
4006
+ /* @__PURE__ */ jsx11(
4007
+ CriterionField,
4008
+ {
4009
+ value: criterion,
4010
+ manual,
4011
+ disabled,
4012
+ modelKey: criterionModelKey(host),
4013
+ emptyText: isWorkflow ? m.workflowNone : void 0,
4014
+ onCommit: (next) => onDispatch({ op: "setCriterion", host, path, criterion: next }),
4015
+ onRemove: () => onDispatch({ op: "setCriterion", host, path, criterion: void 0 })
4016
+ }
4017
+ ),
4018
+ annotationsTarget && /* @__PURE__ */ jsxs10(
4019
+ "div",
4020
+ {
4021
+ "data-testid": "inspector-criterion-annotations",
4022
+ style: { display: "flex", flexDirection: "column", gap: 8, marginTop: 4 },
4023
+ children: [
4024
+ /* @__PURE__ */ jsx11(
4025
+ "span",
4026
+ {
4027
+ style: {
4028
+ fontSize: 11,
4029
+ fontWeight: 600,
4030
+ letterSpacing: "0.08em",
4031
+ textTransform: "uppercase",
4032
+ color: colors.textSecondary
4033
+ },
4034
+ children: "Criterion annotations"
4035
+ }
4036
+ ),
4037
+ /* @__PURE__ */ jsx11(
4038
+ AnnotationsField,
4039
+ {
4040
+ value: criterionAnnotations,
4041
+ disabled,
4042
+ showLabel: false,
4043
+ modelKey: `criterion-annotations-${criterionModelKey(host)}`,
4044
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: annotationsTarget, annotations }),
4045
+ onRemove: () => onDispatch({ op: "setAnnotations", target: annotationsTarget })
4046
+ }
4047
+ )
4048
+ ]
4049
+ }
4050
+ )
4051
+ ] });
4052
+ }
4053
+
3655
4054
  // src/inspector/WorkflowForm.tsx
3656
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
4055
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3657
4056
  function WorkflowForm({
3658
4057
  workflow,
3659
4058
  disabled,
3660
4059
  onDispatch
3661
4060
  }) {
3662
4061
  const messages = useMessages();
3663
- return /* @__PURE__ */ jsxs8(FieldGroup, { title: messages.inspector.properties, children: [
3664
- /* @__PURE__ */ jsx9(
4062
+ return /* @__PURE__ */ jsxs11(FieldGroup, { title: messages.inspector.properties, children: [
4063
+ /* @__PURE__ */ jsx12(
3665
4064
  TextField,
3666
4065
  {
3667
4066
  label: messages.inspector.name,
@@ -3671,7 +4070,7 @@ function WorkflowForm({
3671
4070
  testId: "inspector-workflow-name"
3672
4071
  }
3673
4072
  ),
3674
- /* @__PURE__ */ jsx9(
4073
+ /* @__PURE__ */ jsx12(
3675
4074
  TextField,
3676
4075
  {
3677
4076
  label: messages.inspector.version,
@@ -3686,7 +4085,7 @@ function WorkflowForm({
3686
4085
  testId: "inspector-workflow-version"
3687
4086
  }
3688
4087
  ),
3689
- /* @__PURE__ */ jsx9(
4088
+ /* @__PURE__ */ jsx12(
3690
4089
  TextField,
3691
4090
  {
3692
4091
  label: messages.inspector.description,
@@ -3702,7 +4101,7 @@ function WorkflowForm({
3702
4101
  testId: "inspector-workflow-desc"
3703
4102
  }
3704
4103
  ),
3705
- /* @__PURE__ */ jsx9(
4104
+ /* @__PURE__ */ jsx12(
3706
4105
  CheckboxField,
3707
4106
  {
3708
4107
  label: messages.inspector.active,
@@ -3716,7 +4115,7 @@ function WorkflowForm({
3716
4115
  testId: "inspector-workflow-active"
3717
4116
  }
3718
4117
  ),
3719
- /* @__PURE__ */ jsx9(
4118
+ /* @__PURE__ */ jsx12(
3720
4119
  TextField,
3721
4120
  {
3722
4121
  label: messages.inspector.initialState,
@@ -3731,7 +4130,7 @@ function WorkflowForm({
3731
4130
  testId: "inspector-workflow-initial"
3732
4131
  }
3733
4132
  ),
3734
- /* @__PURE__ */ jsx9(
4133
+ /* @__PURE__ */ jsx12(
3735
4134
  AnnotationsField,
3736
4135
  {
3737
4136
  value: workflow.annotations,
@@ -3740,14 +4139,24 @@ function WorkflowForm({
3740
4139
  onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name }, annotations }),
3741
4140
  onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name } })
3742
4141
  }
4142
+ ),
4143
+ /* @__PURE__ */ jsx12(
4144
+ CriterionSection,
4145
+ {
4146
+ host: { kind: "workflow", workflow: workflow.name },
4147
+ criterion: workflow.criterion,
4148
+ criterionAnnotations: workflow.criterionAnnotations,
4149
+ disabled,
4150
+ onDispatch
4151
+ }
3743
4152
  )
3744
4153
  ] });
3745
4154
  }
3746
4155
 
3747
4156
  // src/inspector/StateForm.tsx
3748
- import { useState as useState7 } from "react";
4157
+ import { useState as useState8 } from "react";
3749
4158
  import { NAME_REGEX } from "@cyoda/workflow-core";
3750
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
4159
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3751
4160
  function StateForm({
3752
4161
  workflow,
3753
4162
  stateCode,
@@ -3758,7 +4167,7 @@ function StateForm({
3758
4167
  onRequestDelete
3759
4168
  }) {
3760
4169
  const messages = useMessages();
3761
- const [renameError, setRenameError] = useState7(null);
4170
+ const [renameError, setRenameError] = useState8(null);
3762
4171
  const outgoing = state.transitions.length;
3763
4172
  const incoming = Object.values(workflow.states).reduce(
3764
4173
  (n, s) => n + s.transitions.filter((t) => t.next === stateCode).length,
@@ -3781,8 +4190,8 @@ function StateForm({
3781
4190
  }
3782
4191
  onDispatch({ op: "renameState", workflow: workflow.name, from: stateCode, to: next });
3783
4192
  };
3784
- return /* @__PURE__ */ jsxs9(FieldGroup, { title: messages.inspector.properties, children: [
3785
- /* @__PURE__ */ jsx10(
4193
+ return /* @__PURE__ */ jsxs12(FieldGroup, { title: messages.inspector.properties, children: [
4194
+ /* @__PURE__ */ jsx13(
3786
4195
  TextField,
3787
4196
  {
3788
4197
  label: messages.inspector.name,
@@ -3793,19 +4202,19 @@ function StateForm({
3793
4202
  testId: "inspector-state-name"
3794
4203
  }
3795
4204
  ),
3796
- renameError && /* @__PURE__ */ jsx10("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
3797
- (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3798
- isInitial && /* @__PURE__ */ jsx10(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
3799
- isTerminal && /* @__PURE__ */ jsx10(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
3800
- isUnreachable && /* @__PURE__ */ jsx10(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
4205
+ renameError && /* @__PURE__ */ jsx13("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4206
+ (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4207
+ isInitial && /* @__PURE__ */ jsx13(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
4208
+ isTerminal && /* @__PURE__ */ jsx13(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
4209
+ isUnreachable && /* @__PURE__ */ jsx13(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
3801
4210
  ] }),
3802
- /* @__PURE__ */ jsxs9("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
4211
+ /* @__PURE__ */ jsxs12("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3803
4212
  outgoing,
3804
4213
  " outgoing \xB7 ",
3805
4214
  incoming,
3806
4215
  " incoming"
3807
4216
  ] }),
3808
- !isInitial && !disabled && /* @__PURE__ */ jsx10(
4217
+ !isInitial && !disabled && /* @__PURE__ */ jsx13(
3809
4218
  "button",
3810
4219
  {
3811
4220
  type: "button",
@@ -3815,7 +4224,7 @@ function StateForm({
3815
4224
  children: "Set as Initial State"
3816
4225
  }
3817
4226
  ),
3818
- issues && issues.length > 0 && /* @__PURE__ */ jsx10("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx10(
4227
+ issues && issues.length > 0 && /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx13(
3819
4228
  "div",
3820
4229
  {
3821
4230
  role: "alert",
@@ -3824,253 +4233,92 @@ function StateForm({
3824
4233
  background: issue.severity === "error" ? colors.dangerBg : colors.warningBg,
3825
4234
  border: `1px solid ${issue.severity === "error" ? colors.dangerBorder : colors.warningBorder}`,
3826
4235
  borderRadius: radii.sm,
3827
- fontSize: 12,
3828
- color: issue.severity === "error" ? colors.danger : colors.warning
3829
- },
3830
- children: issue.message
3831
- },
3832
- `${issue.code}-${i}`
3833
- )) }),
3834
- /* @__PURE__ */ jsx10(
3835
- AnnotationsField,
3836
- {
3837
- value: state.annotations,
3838
- disabled,
3839
- modelKey: `state-${workflow.name}-${stateCode}`,
3840
- onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode }, annotations }),
3841
- onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode } })
3842
- }
3843
- ),
3844
- /* @__PURE__ */ jsx10(
3845
- "button",
3846
- {
3847
- type: "button",
3848
- onClick: onRequestDelete,
3849
- disabled,
3850
- "data-testid": "inspector-state-delete",
3851
- style: dangerBtn2,
3852
- children: "Delete state\u2026"
3853
- }
3854
- )
3855
- ] });
3856
- }
3857
- function StateBadge({ color, bg, label }) {
3858
- return /* @__PURE__ */ jsx10(
3859
- "span",
3860
- {
3861
- style: {
3862
- padding: "2px 8px",
3863
- background: bg,
3864
- color,
3865
- border: `1px solid ${color}`,
3866
- borderRadius: 999,
3867
- fontSize: 11,
3868
- fontWeight: 600
3869
- },
3870
- children: label
3871
- }
3872
- );
3873
- }
3874
- function reachableStates(wf) {
3875
- const visited = /* @__PURE__ */ new Set();
3876
- if (!(wf.initialState in wf.states)) return visited;
3877
- const queue = [wf.initialState];
3878
- visited.add(wf.initialState);
3879
- while (queue.length) {
3880
- const cur = queue.shift();
3881
- for (const t of wf.states[cur]?.transitions ?? []) {
3882
- if (!visited.has(t.next) && t.next in wf.states) {
3883
- visited.add(t.next);
3884
- queue.push(t.next);
3885
- }
3886
- }
3887
- }
3888
- return visited;
3889
- }
3890
- var ghostBtn2 = {
3891
- alignSelf: "flex-start",
3892
- padding: "5px 10px",
3893
- background: "white",
3894
- border: `1px solid ${colors.border}`,
3895
- borderRadius: radii.sm,
3896
- fontSize: 13,
3897
- cursor: "pointer"
3898
- };
3899
- var dangerBtn2 = {
3900
- alignSelf: "flex-start",
3901
- padding: "6px 10px",
3902
- background: colors.dangerBg,
3903
- border: `1px solid ${colors.dangerBorder}`,
3904
- color: colors.danger,
3905
- borderRadius: radii.sm,
3906
- fontSize: 13,
3907
- cursor: "pointer"
3908
- };
3909
-
3910
- // src/inspector/TransitionForm.tsx
3911
- import { useRef as useRef9, useState as useState10 } from "react";
3912
- import { NAME_REGEX as NAME_REGEX3 } from "@cyoda/workflow-core";
3913
-
3914
- // src/inspector/CriterionField.tsx
3915
- import { useEffect as useEffect5, useRef as useRef7, useState as useState8 } from "react";
3916
- import { registerCriterionSchema } from "@cyoda/workflow-monaco";
3917
-
3918
- // src/inspector/criterionJson.ts
3919
- import { CriterionSchema, criterionBlockingError } from "@cyoda/workflow-core";
3920
- function criterionModelUri(key) {
3921
- return `cyoda://criterion/${key}.json`;
3922
- }
3923
- function zodMessage(error) {
3924
- const first = error.issues[0];
3925
- if (!first) return "Invalid criterion.";
3926
- const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3927
- return `${first.message}${path}`;
3928
- }
3929
- function parseCriterionJson(text) {
3930
- let raw;
3931
- try {
3932
- raw = JSON.parse(text);
3933
- } catch {
3934
- return { criterion: null, error: "Invalid JSON." };
3935
- }
3936
- const res = CriterionSchema.safeParse(raw);
3937
- if (res.success) {
3938
- const blocking = criterionBlockingError(res.data);
3939
- if (blocking) return { criterion: null, error: blocking };
3940
- return { criterion: res.data, error: null };
3941
- }
3942
- let friendly = null;
3943
- if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3944
- try {
3945
- friendly = criterionBlockingError(raw);
3946
- } catch {
3947
- friendly = null;
3948
- }
3949
- }
3950
- return { criterion: null, error: friendly ?? zodMessage(res.error) };
3951
- }
3952
-
3953
- // src/inspector/CriterionField.tsx
3954
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3955
- function defaultSimpleCriterion() {
3956
- return { type: "simple", jsonPath: "", operation: "EQUALS" };
3957
- }
3958
- var pretty2 = (c) => JSON.stringify(c, null, 2);
3959
- function CriterionField(props) {
3960
- const m = useMessages().criterion;
3961
- if (props.value === void 0) {
3962
- return /* @__PURE__ */ jsxs10("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3963
- /* @__PURE__ */ jsx11("p", { style: summaryTextStyle, children: props.manual ? m.noneManual : m.noneAutomated }),
3964
- !props.manual && /* @__PURE__ */ jsx11("p", { style: warnStyle2, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3965
- !props.disabled && /* @__PURE__ */ jsx11("button", { type: "button", style: primaryBtnStyle, "data-testid": "inspector-criterion-add", onClick: () => props.onCommit(defaultSimpleCriterion()), children: m.add })
3966
- ] });
3967
- }
3968
- return /* @__PURE__ */ jsx11(CriterionEditor, { ...props, value: props.value }, props.modelKey);
3969
- }
3970
- function CriterionEditor({ value, disabled, modelKey, onCommit, onRemove }) {
3971
- const messages = useMessages();
3972
- const m = messages.criterion;
3973
- const [expanded, setExpanded] = useState8(false);
3974
- const [buffer, setBuffer] = useState8(() => pretty2(value));
3975
- const [docChanged, setDocChanged] = useState8(false);
3976
- const prevValueRef = useRef7(value);
3977
- useEffect5(() => {
3978
- if (sameJson(prevValueRef.current, value)) return;
3979
- const parsed = parseCriterionJson(buffer).criterion;
3980
- if (parsed !== null && sameJson(parsed, value)) {
3981
- setDocChanged(false);
3982
- } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3983
- setBuffer(pretty2(value));
3984
- setDocChanged(false);
3985
- } else {
3986
- setDocChanged(true);
3987
- }
3988
- prevValueRef.current = value;
3989
- }, [value, buffer]);
3990
- const result = parseCriterionJson(buffer);
3991
- const dirty = result.criterion !== null && !sameJson(result.criterion, value);
3992
- const applyEnabled = !disabled && result.criterion !== null && dirty;
3993
- const canRevert = buffer !== pretty2(value);
3994
- const apply = () => {
3995
- if (!applyEnabled || result.criterion === null) return;
3996
- onCommit(result.criterion);
3997
- setDocChanged(false);
3998
- setExpanded(false);
3999
- };
4000
- const revert = () => {
4001
- setBuffer(pretty2(value));
4002
- setDocChanged(false);
4003
- };
4004
- return /* @__PURE__ */ jsxs10("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
4005
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
4006
- /* @__PURE__ */ jsx11("span", { style: metaChipStyle, children: value.type }),
4007
- /* @__PURE__ */ jsx11("span", { style: { flex: 1 } }),
4008
- !disabled && !expanded && /* @__PURE__ */ jsx11("button", { type: "button", style: ghostBtnStyle, "data-testid": "inspector-criterion-edit", onClick: () => setExpanded(true), children: m.edit }),
4009
- !disabled && /* @__PURE__ */ jsx11("button", { type: "button", style: destructiveBtnStyle, "data-testid": "inspector-criterion-remove", onClick: onRemove, children: m.remove })
4010
- ] }),
4011
- !expanded && /* @__PURE__ */ jsx11(CompactJson, { criterion: value }),
4012
- expanded && /* @__PURE__ */ jsxs10(Fragment4, { children: [
4013
- /* @__PURE__ */ jsx11(
4014
- JsonMonacoField,
4015
- {
4016
- buffer,
4017
- disabled,
4018
- modelUri: criterionModelUri(modelKey),
4019
- onChange: setBuffer,
4020
- seed: buffer,
4021
- registerSchema: registerCriterionSchema,
4022
- testId: "criterion-json-editor"
4023
- }
4024
- ),
4025
- result.error && /* @__PURE__ */ jsx11("div", { role: "alert", "data-testid": "criterion-error", style: errorStyle2, children: result.error }),
4026
- docChanged && /* @__PURE__ */ jsx11("div", { role: "alert", "data-testid": "criterion-doc-changed", style: warnLineStyle, children: messages.inspector.annotationsDocChanged }),
4027
- !disabled && /* @__PURE__ */ jsxs10("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4028
- /* @__PURE__ */ jsx11("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 }),
4029
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtnStyle, "data-testid": "inspector-criterion-revert", children: m.revert }),
4030
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: () => setExpanded(false), style: ghostBtnStyle, "data-testid": "inspector-criterion-collapse", children: m.collapse })
4031
- ] })
4032
- ] })
4236
+ fontSize: 12,
4237
+ color: issue.severity === "error" ? colors.danger : colors.warning
4238
+ },
4239
+ children: issue.message
4240
+ },
4241
+ `${issue.code}-${i}`
4242
+ )) }),
4243
+ /* @__PURE__ */ jsx13(
4244
+ AnnotationsField,
4245
+ {
4246
+ value: state.annotations,
4247
+ disabled,
4248
+ modelKey: `state-${workflow.name}-${stateCode}`,
4249
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode }, annotations }),
4250
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode } })
4251
+ }
4252
+ ),
4253
+ /* @__PURE__ */ jsx13(
4254
+ "button",
4255
+ {
4256
+ type: "button",
4257
+ onClick: onRequestDelete,
4258
+ disabled,
4259
+ "data-testid": "inspector-state-delete",
4260
+ style: dangerBtn2,
4261
+ children: "Delete state\u2026"
4262
+ }
4263
+ )
4033
4264
  ] });
4034
4265
  }
4035
- function CompactJson({ criterion }) {
4036
- const text = JSON.stringify(criterion);
4037
- const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
4038
- return /* @__PURE__ */ jsx11("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 });
4039
- }
4040
- var cardStyle = { display: "flex", flexDirection: "column", gap: 8, padding: 10, border: `1px solid ${colors.border}`, borderRadius: radii.md, background: colors.surface };
4041
- var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
4042
- var warnStyle2 = { margin: 0, padding: "6px 8px", background: colors.warningBg, border: `1px solid ${colors.warningBorder}`, borderRadius: radii.sm, color: colors.warning, fontSize: 11 };
4043
- var errorStyle2 = { color: colors.danger, fontSize: 11 };
4044
- var warnLineStyle = { color: colors.warning, fontSize: 11 };
4045
-
4046
- // src/inspector/CriterionForm.tsx
4047
- import { jsx as jsx12 } from "react/jsx-runtime";
4048
- function criterionModelKey(host) {
4049
- if (host.kind === "transition") return `transition-${host.transitionUuid}`;
4050
- if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
4051
- return `host-${host.workflow}`;
4052
- }
4053
- function CriterionSection({
4054
- host,
4055
- manual,
4056
- criterion,
4057
- disabled,
4058
- onDispatch,
4059
- onSelectionChange: _onSelectionChange
4060
- }) {
4061
- const path = ["criterion"];
4062
- return /* @__PURE__ */ jsx12(
4063
- CriterionField,
4266
+ function StateBadge({ color, bg, label }) {
4267
+ return /* @__PURE__ */ jsx13(
4268
+ "span",
4064
4269
  {
4065
- value: criterion,
4066
- manual,
4067
- disabled,
4068
- modelKey: criterionModelKey(host),
4069
- onCommit: (next) => onDispatch({ op: "setCriterion", host, path, criterion: next }),
4070
- onRemove: () => onDispatch({ op: "setCriterion", host, path, criterion: void 0 })
4270
+ style: {
4271
+ padding: "2px 8px",
4272
+ background: bg,
4273
+ color,
4274
+ border: `1px solid ${color}`,
4275
+ borderRadius: 999,
4276
+ fontSize: 11,
4277
+ fontWeight: 600
4278
+ },
4279
+ children: label
4071
4280
  }
4072
4281
  );
4073
4282
  }
4283
+ function reachableStates(wf) {
4284
+ const visited = /* @__PURE__ */ new Set();
4285
+ if (!(wf.initialState in wf.states)) return visited;
4286
+ const queue = [wf.initialState];
4287
+ visited.add(wf.initialState);
4288
+ while (queue.length) {
4289
+ const cur = queue.shift();
4290
+ for (const t of wf.states[cur]?.transitions ?? []) {
4291
+ if (!visited.has(t.next) && t.next in wf.states) {
4292
+ visited.add(t.next);
4293
+ queue.push(t.next);
4294
+ }
4295
+ }
4296
+ }
4297
+ return visited;
4298
+ }
4299
+ var ghostBtn2 = {
4300
+ alignSelf: "flex-start",
4301
+ padding: "5px 10px",
4302
+ background: "white",
4303
+ border: `1px solid ${colors.border}`,
4304
+ borderRadius: radii.sm,
4305
+ fontSize: 13,
4306
+ cursor: "pointer"
4307
+ };
4308
+ var dangerBtn2 = {
4309
+ alignSelf: "flex-start",
4310
+ padding: "6px 10px",
4311
+ background: colors.dangerBg,
4312
+ border: `1px solid ${colors.dangerBorder}`,
4313
+ color: colors.danger,
4314
+ borderRadius: radii.sm,
4315
+ fontSize: 13,
4316
+ cursor: "pointer"
4317
+ };
4318
+
4319
+ // src/inspector/TransitionForm.tsx
4320
+ import { useRef as useRef9, useState as useState10 } from "react";
4321
+ import { NAME_REGEX as NAME_REGEX3 } from "@cyoda/workflow-core";
4074
4322
 
4075
4323
  // src/inspector/ProcessorForm.tsx
4076
4324
  import { useEffect as useEffect7, useState as useState9 } from "react";
@@ -4080,7 +4328,7 @@ import {
4080
4328
 
4081
4329
  // src/modals/DeleteStateModal.tsx
4082
4330
  import { useEffect as useEffect6, useMemo as useMemo3, useRef as useRef8 } from "react";
4083
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
4331
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
4084
4332
  function countAffected(doc, workflow, stateCode) {
4085
4333
  let outgoing = 0;
4086
4334
  let incoming = 0;
@@ -4106,20 +4354,20 @@ function DeleteStateModal({
4106
4354
  () => countAffected(doc, workflow, stateCode),
4107
4355
  [doc, workflow, stateCode]
4108
4356
  );
4109
- return /* @__PURE__ */ jsxs11(ModalFrame, { onCancel, children: [
4110
- /* @__PURE__ */ jsx13("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
4111
- /* @__PURE__ */ jsx13("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
4112
- /* @__PURE__ */ jsxs11("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
4113
- /* @__PURE__ */ jsx13("strong", { children: stateCode }),
4114
- /* @__PURE__ */ jsxs11("div", { style: { color: colors.textSecondary }, children: [
4357
+ return /* @__PURE__ */ jsxs13(ModalFrame, { onCancel, children: [
4358
+ /* @__PURE__ */ jsx14("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
4359
+ /* @__PURE__ */ jsx14("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
4360
+ /* @__PURE__ */ jsxs13("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
4361
+ /* @__PURE__ */ jsx14("strong", { children: stateCode }),
4362
+ /* @__PURE__ */ jsxs13("div", { style: { color: colors.textSecondary }, children: [
4115
4363
  messages.confirmDelete.transitionsAffected,
4116
4364
  ": ",
4117
4365
  counts.outgoing + counts.incoming
4118
4366
  ] })
4119
4367
  ] }),
4120
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
4121
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
4122
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: onConfirm, style: dangerBtn3, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
4368
+ /* @__PURE__ */ jsxs13("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
4369
+ /* @__PURE__ */ jsx14("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
4370
+ /* @__PURE__ */ jsx14("button", { type: "button", onClick: onConfirm, style: dangerBtn3, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
4123
4371
  ] })
4124
4372
  ] });
4125
4373
  }
@@ -4143,7 +4391,7 @@ function ModalFrame({
4143
4391
  previousFocusRef.current?.focus?.();
4144
4392
  };
4145
4393
  }, []);
4146
- return /* @__PURE__ */ jsx13(
4394
+ return /* @__PURE__ */ jsx14(
4147
4395
  "div",
4148
4396
  {
4149
4397
  onClick: onCancel,
@@ -4163,7 +4411,7 @@ function ModalFrame({
4163
4411
  zIndex: 1e3
4164
4412
  },
4165
4413
  "data-testid": "modal-backdrop",
4166
- children: /* @__PURE__ */ jsx13(
4414
+ children: /* @__PURE__ */ jsx14(
4167
4415
  "div",
4168
4416
  {
4169
4417
  ref: frameRef,
@@ -4205,7 +4453,7 @@ var dangerBtn3 = {
4205
4453
  };
4206
4454
 
4207
4455
  // src/inspector/ProcessorForm.tsx
4208
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
4456
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
4209
4457
  var EXECUTION_MODES = [
4210
4458
  "ASYNC_NEW_TX",
4211
4459
  "ASYNC_SAME_TX",
@@ -4237,7 +4485,8 @@ function toDraft(processor) {
4237
4485
  retryPolicy: externalized?.config?.retryPolicy ?? "",
4238
4486
  context: externalized?.config?.context ?? "",
4239
4487
  asyncResult: externalized?.config?.asyncResult ?? false,
4240
- crossoverToAsyncMs: externalized?.config?.crossoverToAsyncMs !== void 0 ? String(externalized.config.crossoverToAsyncMs) : ""
4488
+ crossoverToAsyncMs: externalized?.config?.crossoverToAsyncMs !== void 0 ? String(externalized.config.crossoverToAsyncMs) : "",
4489
+ annotations: externalized?.annotations
4241
4490
  };
4242
4491
  }
4243
4492
  function toProcessor(draft) {
@@ -4259,7 +4508,8 @@ function toProcessor(draft) {
4259
4508
  name: draft.name.trim(),
4260
4509
  executionMode: draft.executionMode,
4261
4510
  ...draft.executionMode === "COMMIT_BEFORE_DISPATCH" && draft.startNewTxOnDispatch ? { startNewTxOnDispatch: true } : {},
4262
- ...Object.keys(config).length > 0 ? { config } : {}
4511
+ ...Object.keys(config).length > 0 ? { config } : {},
4512
+ ...draft.annotations !== void 0 ? { annotations: draft.annotations } : {}
4263
4513
  };
4264
4514
  }
4265
4515
  function validateDraft(draft, existingNames, originalName) {
@@ -4311,13 +4561,13 @@ function ProcessorEditorModal({
4311
4561
  if (disabled || error) return;
4312
4562
  onApply(toProcessor(draft));
4313
4563
  };
4314
- return /* @__PURE__ */ jsx14(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ jsxs12("div", { style: modalStyle, "data-testid": "processor-editor-modal", children: [
4315
- /* @__PURE__ */ jsxs12("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4316
- /* @__PURE__ */ jsx14("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4317
- /* @__PURE__ */ jsx14("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4564
+ return /* @__PURE__ */ jsx15(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ jsxs14("div", { style: modalStyle, "data-testid": "processor-editor-modal", children: [
4565
+ /* @__PURE__ */ jsxs14("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4566
+ /* @__PURE__ */ jsx15("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4567
+ /* @__PURE__ */ jsx15("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4318
4568
  ] }),
4319
- /* @__PURE__ */ jsxs12("div", { style: modalBodyStyle, children: [
4320
- /* @__PURE__ */ jsx14(FormField, { label: "Name", children: /* @__PURE__ */ jsx14(
4569
+ /* @__PURE__ */ jsxs14("div", { style: modalBodyStyle, children: [
4570
+ /* @__PURE__ */ jsx15(FormField, { label: "Name", children: /* @__PURE__ */ jsx15(
4321
4571
  "input",
4322
4572
  {
4323
4573
  type: "text",
@@ -4327,17 +4577,42 @@ function ProcessorEditorModal({
4327
4577
  style: inputStyle2
4328
4578
  }
4329
4579
  ) }),
4330
- /* @__PURE__ */ jsx14(FormField, { label: "Execution mode", children: /* @__PURE__ */ jsx14(
4580
+ /* @__PURE__ */ jsx15(FormField, { label: "Execution mode", children: /* @__PURE__ */ jsx15(
4331
4581
  CustomSelectInput,
4332
4582
  {
4333
4583
  value: draft.executionMode,
4334
4584
  options: EXECUTION_MODES.map((mode) => ({ value: mode, label: mode })),
4335
- onChange: (next) => setDraft((current) => ({ ...current, executionMode: next })),
4585
+ onChange: (next) => setDraft((current) => ({
4586
+ ...current,
4587
+ executionMode: next,
4588
+ // startNewTxOnDispatch is only valid for COMMIT_BEFORE_DISPATCH.
4589
+ startNewTxOnDispatch: next === "COMMIT_BEFORE_DISPATCH" ? current.startNewTxOnDispatch : false
4590
+ })),
4336
4591
  testId: "processor-execution-mode"
4337
4592
  }
4338
4593
  ) }),
4339
- /* @__PURE__ */ jsxs12("label", { style: checkboxRowStyle, children: [
4340
- /* @__PURE__ */ jsx14(
4594
+ /* @__PURE__ */ jsxs14(
4595
+ "label",
4596
+ {
4597
+ style: draft.executionMode === "COMMIT_BEFORE_DISPATCH" ? checkboxRowStyle : { ...checkboxRowStyle, opacity: 0.5 },
4598
+ title: "Only for COMMIT_BEFORE_DISPATCH: open a fresh transaction context for the dispatched call.",
4599
+ children: [
4600
+ /* @__PURE__ */ jsx15(
4601
+ "input",
4602
+ {
4603
+ type: "checkbox",
4604
+ checked: draft.startNewTxOnDispatch,
4605
+ disabled: disabled || draft.executionMode !== "COMMIT_BEFORE_DISPATCH",
4606
+ onChange: (event) => setDraft((current) => ({ ...current, startNewTxOnDispatch: event.target.checked })),
4607
+ "data-testid": "processor-start-new-tx"
4608
+ }
4609
+ ),
4610
+ /* @__PURE__ */ jsx15("span", { children: "Start new transaction on dispatch" })
4611
+ ]
4612
+ }
4613
+ ),
4614
+ /* @__PURE__ */ jsxs14("label", { style: checkboxRowStyle, children: [
4615
+ /* @__PURE__ */ jsx15(
4341
4616
  "input",
4342
4617
  {
4343
4618
  type: "checkbox",
@@ -4345,9 +4620,9 @@ function ProcessorEditorModal({
4345
4620
  onChange: (event) => setDraft((current) => ({ ...current, attachEntity: event.target.checked }))
4346
4621
  }
4347
4622
  ),
4348
- /* @__PURE__ */ jsx14("span", { children: "Attach entity" })
4623
+ /* @__PURE__ */ jsx15("span", { children: "Attach entity" })
4349
4624
  ] }),
4350
- /* @__PURE__ */ jsx14(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ jsx14(
4625
+ /* @__PURE__ */ jsx15(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ jsx15(
4351
4626
  "input",
4352
4627
  {
4353
4628
  type: "text",
@@ -4360,7 +4635,7 @@ function ProcessorEditorModal({
4360
4635
  style: inputStyle2
4361
4636
  }
4362
4637
  ) }),
4363
- /* @__PURE__ */ jsx14(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ jsx14(
4638
+ /* @__PURE__ */ jsx15(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ jsx15(
4364
4639
  "input",
4365
4640
  {
4366
4641
  type: "text",
@@ -4372,17 +4647,33 @@ function ProcessorEditorModal({
4372
4647
  style: inputStyle2
4373
4648
  }
4374
4649
  ) }),
4375
- /* @__PURE__ */ jsx14(FormField, { label: "Retry policy", children: /* @__PURE__ */ jsx14(
4650
+ /* @__PURE__ */ jsx15(FormField, { label: "Retry policy", children: /* @__PURE__ */ jsx15(
4651
+ CustomSelectInput,
4652
+ {
4653
+ value: draft.retryPolicy,
4654
+ options: [
4655
+ { value: "", label: "Default (FIXED)" },
4656
+ { value: "NONE", label: "NONE" },
4657
+ { value: "FIXED", label: "FIXED" }
4658
+ ],
4659
+ onChange: (next) => setDraft((current) => ({ ...current, retryPolicy: next })),
4660
+ testId: "processor-retry-policy"
4661
+ }
4662
+ ) }),
4663
+ /* @__PURE__ */ jsx15(FormField, { label: "Context", children: /* @__PURE__ */ jsx15(
4376
4664
  "input",
4377
4665
  {
4378
4666
  type: "text",
4379
- value: draft.retryPolicy,
4380
- onChange: (event) => setDraft((current) => ({ ...current, retryPolicy: event.target.value })),
4381
- style: inputStyle2
4667
+ value: draft.context,
4668
+ placeholder: "passed verbatim as request parameters",
4669
+ disabled,
4670
+ onChange: (event) => setDraft((current) => ({ ...current, context: event.target.value })),
4671
+ "data-testid": "processor-context-input",
4672
+ style: disabled ? disabledInputStyle : inputStyle2
4382
4673
  }
4383
4674
  ) }),
4384
- /* @__PURE__ */ jsxs12("label", { style: checkboxRowStyle, children: [
4385
- /* @__PURE__ */ jsx14(
4675
+ /* @__PURE__ */ jsxs14("label", { style: checkboxRowStyle, children: [
4676
+ /* @__PURE__ */ jsx15(
4386
4677
  "input",
4387
4678
  {
4388
4679
  type: "checkbox",
@@ -4395,9 +4686,9 @@ function ProcessorEditorModal({
4395
4686
  "data-testid": "processor-async-result"
4396
4687
  }
4397
4688
  ),
4398
- /* @__PURE__ */ jsx14("span", { children: "Async result" })
4689
+ /* @__PURE__ */ jsx15("span", { children: "Async result" })
4399
4690
  ] }),
4400
- /* @__PURE__ */ jsx14(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ jsx14(
4691
+ /* @__PURE__ */ jsx15(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ jsx15(
4401
4692
  "input",
4402
4693
  {
4403
4694
  type: "text",
@@ -4412,10 +4703,27 @@ function ProcessorEditorModal({
4412
4703
  }
4413
4704
  ) })
4414
4705
  ] }),
4415
- error && /* @__PURE__ */ jsx14("div", { role: "alert", style: errorStyle3, "data-testid": "processor-modal-error", children: error }),
4416
- /* @__PURE__ */ jsxs12("footer", { style: modalFooterStyle, children: [
4417
- /* @__PURE__ */ jsx14("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4418
- /* @__PURE__ */ jsx14(
4706
+ /* @__PURE__ */ jsx15(
4707
+ "div",
4708
+ {
4709
+ "data-testid": "processor-annotations",
4710
+ style: { display: "flex", flexDirection: "column", gap: 8, gridColumn: "1 / -1" },
4711
+ children: /* @__PURE__ */ jsx15(
4712
+ AnnotationsField,
4713
+ {
4714
+ value: draft.annotations,
4715
+ disabled,
4716
+ modelKey: `processor-${initialProcessor?.name ?? "new"}`,
4717
+ onCommit: (a) => setDraft((c) => ({ ...c, annotations: a })),
4718
+ onRemove: () => setDraft((c) => ({ ...c, annotations: void 0 }))
4719
+ }
4720
+ )
4721
+ }
4722
+ ),
4723
+ error && /* @__PURE__ */ jsx15("div", { role: "alert", style: errorStyle3, "data-testid": "processor-modal-error", children: error }),
4724
+ /* @__PURE__ */ jsxs14("footer", { style: modalFooterStyle, children: [
4725
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4726
+ /* @__PURE__ */ jsx15(
4419
4727
  "button",
4420
4728
  {
4421
4729
  type: "button",
@@ -4433,8 +4741,8 @@ function FormField({
4433
4741
  label,
4434
4742
  children
4435
4743
  }) {
4436
- return /* @__PURE__ */ jsxs12("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4437
- /* @__PURE__ */ jsx14("span", { style: labelStyle2, children: label }),
4744
+ return /* @__PURE__ */ jsxs14("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4745
+ /* @__PURE__ */ jsx15("span", { style: labelStyle3, children: label }),
4438
4746
  children
4439
4747
  ] });
4440
4748
  }
@@ -4449,17 +4757,17 @@ function ProcessorForm({
4449
4757
  }) {
4450
4758
  const messages = useMessages();
4451
4759
  const [modalOpen, setModalOpen] = useState9(false);
4452
- return /* @__PURE__ */ jsxs12("div", { style: summaryCardStyle, children: [
4453
- /* @__PURE__ */ jsxs12("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4454
- /* @__PURE__ */ jsxs12("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4455
- /* @__PURE__ */ jsx14("strong", { style: { fontSize: 13 }, children: processor.name }),
4456
- /* @__PURE__ */ jsx14("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4760
+ return /* @__PURE__ */ jsxs14("div", { style: summaryCardStyle, children: [
4761
+ /* @__PURE__ */ jsxs14("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4762
+ /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4763
+ /* @__PURE__ */ jsx15("strong", { style: { fontSize: 13 }, children: processor.name }),
4764
+ /* @__PURE__ */ jsx15("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4457
4765
  ] }),
4458
- /* @__PURE__ */ jsx14("span", { style: chipStyle, children: processor.type })
4766
+ /* @__PURE__ */ jsx15("span", { style: chipStyle, children: processor.type })
4459
4767
  ] }),
4460
- /* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4461
- /* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4462
- /* @__PURE__ */ jsx14(
4768
+ /* @__PURE__ */ jsxs14("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4769
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4770
+ /* @__PURE__ */ jsx15(
4463
4771
  "button",
4464
4772
  {
4465
4773
  type: "button",
@@ -4474,7 +4782,7 @@ function ProcessorForm({
4474
4782
  children: messages.inspector.moveUp
4475
4783
  }
4476
4784
  ),
4477
- /* @__PURE__ */ jsx14(
4785
+ /* @__PURE__ */ jsx15(
4478
4786
  "button",
4479
4787
  {
4480
4788
  type: "button",
@@ -4489,7 +4797,7 @@ function ProcessorForm({
4489
4797
  children: messages.inspector.moveDown
4490
4798
  }
4491
4799
  ),
4492
- /* @__PURE__ */ jsx14(
4800
+ /* @__PURE__ */ jsx15(
4493
4801
  "button",
4494
4802
  {
4495
4803
  type: "button",
@@ -4501,7 +4809,7 @@ function ProcessorForm({
4501
4809
  }
4502
4810
  )
4503
4811
  ] }),
4504
- modalOpen && /* @__PURE__ */ jsx14(
4812
+ modalOpen && /* @__PURE__ */ jsx15(
4505
4813
  ProcessorEditorModal,
4506
4814
  {
4507
4815
  title: `Edit ${processor.name}`,
@@ -4521,7 +4829,7 @@ function ProcessorForm({
4521
4829
  )
4522
4830
  ] });
4523
4831
  }
4524
- var labelStyle2 = {
4832
+ var labelStyle3 = {
4525
4833
  fontSize: 12,
4526
4834
  color: colors.textSecondary,
4527
4835
  marginBottom: 2
@@ -4615,7 +4923,7 @@ var summaryCardStyle = {
4615
4923
  };
4616
4924
 
4617
4925
  // src/inspector/TransitionForm.tsx
4618
- import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
4926
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
4619
4927
  function TransitionForm({
4620
4928
  workflow,
4621
4929
  stateCode,
@@ -4736,9 +5044,9 @@ function TransitionForm({
4736
5044
  index: index + 1
4737
5045
  });
4738
5046
  };
4739
- return /* @__PURE__ */ jsxs13("div", { style: transitionFormStyle, children: [
4740
- /* @__PURE__ */ jsxs13(FieldGroup, { title: messages.inspector.properties, children: [
4741
- /* @__PURE__ */ jsx15(
5047
+ return /* @__PURE__ */ jsxs15("div", { style: transitionFormStyle, children: [
5048
+ /* @__PURE__ */ jsxs15(FieldGroup, { title: messages.inspector.properties, children: [
5049
+ /* @__PURE__ */ jsx16(
4742
5050
  TextField,
4743
5051
  {
4744
5052
  label: messages.inspector.name,
@@ -4749,90 +5057,96 @@ function TransitionForm({
4749
5057
  testId: "inspector-transition-name"
4750
5058
  }
4751
5059
  ),
4752
- renameError && /* @__PURE__ */ jsx15("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4753
- !disabled && /* @__PURE__ */ jsx15(
4754
- SelectField,
4755
- {
4756
- label: "Source state",
4757
- value: stateCode,
4758
- options: stateOptions,
4759
- disabled,
4760
- onChange: (toState) => {
4761
- if (toState === stateCode) return;
4762
- onDispatch({
4763
- op: "moveTransitionSource",
4764
- workflow: workflow.name,
4765
- fromState: stateCode,
4766
- toState,
4767
- transitionName: transition.name
4768
- });
4769
- },
4770
- testId: "inspector-transition-source-state"
4771
- }
4772
- ),
4773
- /* @__PURE__ */ jsx15(
4774
- SelectField,
4775
- {
4776
- label: "Target state",
4777
- value: transition.next,
4778
- options: stateOptions,
4779
- disabled,
4780
- onChange: (next) => update({ next }),
4781
- testId: "inspector-transition-next"
4782
- }
4783
- ),
4784
- /* @__PURE__ */ jsx15(
4785
- SelectField,
4786
- {
4787
- label: messages.inspector.transitionType,
4788
- value: transition.manual ? "manual" : "automated",
4789
- options: [
4790
- { value: "automated", label: messages.inspector.automated },
4791
- { value: "manual", label: messages.inspector.manual }
4792
- ],
4793
- disabled,
4794
- onChange: (next) => update({ manual: next === "manual" }),
4795
- testId: "inspector-transition-manual"
4796
- }
4797
- ),
4798
- /* @__PURE__ */ jsx15(
4799
- CheckboxField,
4800
- {
4801
- label: messages.inspector.disabled,
4802
- checked: transition.disabled,
4803
- disabled,
4804
- onChange: (next) => update({ disabled: next }),
4805
- testId: "inspector-transition-disabled"
4806
- }
4807
- ),
4808
- /* @__PURE__ */ jsx15(
4809
- AnchorSelect,
4810
- {
4811
- label: messages.inspector.sourceAnchor,
4812
- value: anchors?.source,
4813
- disabled,
4814
- messages,
4815
- onChange: (next) => setAnchor("source", next),
4816
- testId: "inspector-transition-source-anchor"
4817
- }
4818
- ),
4819
- /* @__PURE__ */ jsx15(
4820
- AnchorSelect,
4821
- {
4822
- label: messages.inspector.targetAnchor,
4823
- value: anchors?.target,
4824
- disabled,
4825
- messages,
4826
- onChange: (next) => setAnchor("target", next),
4827
- testId: "inspector-transition-target-anchor"
4828
- }
4829
- ),
4830
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4831
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 6 }, children: [
4832
- /* @__PURE__ */ jsx15("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
4833
- /* @__PURE__ */ jsx15("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
5060
+ renameError && /* @__PURE__ */ jsx16("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
5061
+ /* @__PURE__ */ jsxs15("div", { style: twoColStyle, children: [
5062
+ !disabled && /* @__PURE__ */ jsx16(
5063
+ SelectField,
5064
+ {
5065
+ label: "Source state",
5066
+ value: stateCode,
5067
+ options: stateOptions,
5068
+ disabled,
5069
+ onChange: (toState) => {
5070
+ if (toState === stateCode) return;
5071
+ onDispatch({
5072
+ op: "moveTransitionSource",
5073
+ workflow: workflow.name,
5074
+ fromState: stateCode,
5075
+ toState,
5076
+ transitionName: transition.name
5077
+ });
5078
+ },
5079
+ testId: "inspector-transition-source-state"
5080
+ }
5081
+ ),
5082
+ /* @__PURE__ */ jsx16(
5083
+ SelectField,
5084
+ {
5085
+ label: "Target state",
5086
+ value: transition.next,
5087
+ options: stateOptions,
5088
+ disabled,
5089
+ onChange: (next) => update({ next }),
5090
+ testId: "inspector-transition-next"
5091
+ }
5092
+ )
5093
+ ] }),
5094
+ /* @__PURE__ */ jsxs15("div", { style: twoColStyle, children: [
5095
+ /* @__PURE__ */ jsx16(
5096
+ SelectField,
5097
+ {
5098
+ label: messages.inspector.transitionType,
5099
+ value: transition.manual ? "manual" : "automated",
5100
+ options: [
5101
+ { value: "automated", label: messages.inspector.automated },
5102
+ { value: "manual", label: messages.inspector.manual }
5103
+ ],
5104
+ disabled,
5105
+ onChange: (next) => update({ manual: next === "manual" }),
5106
+ testId: "inspector-transition-manual"
5107
+ }
5108
+ ),
5109
+ /* @__PURE__ */ jsx16(
5110
+ CheckboxField,
5111
+ {
5112
+ label: messages.inspector.disabled,
5113
+ checked: transition.disabled,
5114
+ disabled,
5115
+ onChange: (next) => update({ disabled: next }),
5116
+ testId: "inspector-transition-disabled"
5117
+ }
5118
+ )
5119
+ ] }),
5120
+ /* @__PURE__ */ jsxs15("div", { style: twoColStyle, children: [
5121
+ /* @__PURE__ */ jsx16(
5122
+ AnchorSelect,
5123
+ {
5124
+ label: messages.inspector.sourceAnchor,
5125
+ value: anchors?.source,
5126
+ disabled,
5127
+ messages,
5128
+ onChange: (next) => setAnchor("source", next),
5129
+ testId: "inspector-transition-source-anchor"
5130
+ }
5131
+ ),
5132
+ /* @__PURE__ */ jsx16(
5133
+ AnchorSelect,
5134
+ {
5135
+ label: messages.inspector.targetAnchor,
5136
+ value: anchors?.target,
5137
+ disabled,
5138
+ messages,
5139
+ onChange: (next) => setAnchor("target", next),
5140
+ testId: "inspector-transition-target-anchor"
5141
+ }
5142
+ )
5143
+ ] }),
5144
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
5145
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 6 }, children: [
5146
+ /* @__PURE__ */ jsx16("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
5147
+ /* @__PURE__ */ jsx16("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
4834
5148
  ] }),
4835
- /* @__PURE__ */ jsx15(
5149
+ /* @__PURE__ */ jsx16(
4836
5150
  "p",
4837
5151
  {
4838
5152
  style: {
@@ -4846,8 +5160,8 @@ function TransitionForm({
4846
5160
  }
4847
5161
  )
4848
5162
  ] }),
4849
- /* @__PURE__ */ jsx15("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4850
- /* @__PURE__ */ jsx15(
5163
+ /* @__PURE__ */ jsx16("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
5164
+ /* @__PURE__ */ jsx16(
4851
5165
  "button",
4852
5166
  {
4853
5167
  type: "button",
@@ -4858,8 +5172,8 @@ function TransitionForm({
4858
5172
  children: "Delete transition"
4859
5173
  }
4860
5174
  ),
4861
- /* @__PURE__ */ jsx15("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4862
- issues && issues.length > 0 && /* @__PURE__ */ jsx15("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx15(
5175
+ /* @__PURE__ */ jsx16("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
5176
+ issues && issues.length > 0 && /* @__PURE__ */ jsx16("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx16(
4863
5177
  "div",
4864
5178
  {
4865
5179
  role: "alert",
@@ -4876,12 +5190,12 @@ function TransitionForm({
4876
5190
  `${issue.code}-${i}`
4877
5191
  )) })
4878
5192
  ] }),
4879
- /* @__PURE__ */ jsx15(
5193
+ /* @__PURE__ */ jsx16(
4880
5194
  TransitionSection,
4881
5195
  {
4882
5196
  title: messages.inspector.criteria,
4883
5197
  testId: "inspector-transition-criteria-section",
4884
- children: /* @__PURE__ */ jsx15(
5198
+ children: /* @__PURE__ */ jsx16(
4885
5199
  CriterionSection,
4886
5200
  {
4887
5201
  host,
@@ -4890,6 +5204,7 @@ function TransitionForm({
4890
5204
  targetState: transition.next,
4891
5205
  manual: transition.manual,
4892
5206
  criterion: transition.criterion,
5207
+ criterionAnnotations: transition.criterionAnnotations,
4893
5208
  disabled,
4894
5209
  onDispatch,
4895
5210
  onSelectionChange
@@ -4897,18 +5212,18 @@ function TransitionForm({
4897
5212
  )
4898
5213
  }
4899
5214
  ),
4900
- /* @__PURE__ */ jsxs13(
5215
+ /* @__PURE__ */ jsxs15(
4901
5216
  TransitionSection,
4902
5217
  {
4903
5218
  title: "Scheduled transition",
4904
5219
  testId: "inspector-transition-schedule-section",
4905
5220
  children: [
4906
- /* @__PURE__ */ jsxs13(
5221
+ /* @__PURE__ */ jsxs15(
4907
5222
  "label",
4908
5223
  {
4909
5224
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: 8, fontSize: 12, color: colors.textSecondary, cursor: "pointer" },
4910
5225
  children: [
4911
- /* @__PURE__ */ jsx15(
5226
+ /* @__PURE__ */ jsx16(
4912
5227
  "input",
4913
5228
  {
4914
5229
  type: "checkbox",
@@ -4928,14 +5243,14 @@ function TransitionForm({
4928
5243
  }
4929
5244
  }
4930
5245
  ),
4931
- /* @__PURE__ */ jsx15("span", { children: "Enable schedule" })
5246
+ /* @__PURE__ */ jsx16("span", { children: "Enable schedule" })
4932
5247
  ]
4933
5248
  }
4934
5249
  ),
4935
- transition.schedule !== void 0 && /* @__PURE__ */ jsxs13(Fragment5, { children: [
4936
- /* @__PURE__ */ jsxs13("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4937
- /* @__PURE__ */ jsx15("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
4938
- /* @__PURE__ */ jsx15(
5250
+ transition.schedule !== void 0 && /* @__PURE__ */ jsxs15("div", { style: twoColStyle, children: [
5251
+ /* @__PURE__ */ jsxs15("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5252
+ /* @__PURE__ */ jsx16("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
5253
+ /* @__PURE__ */ jsx16(
4939
5254
  "input",
4940
5255
  {
4941
5256
  type: "text",
@@ -4951,9 +5266,9 @@ function TransitionForm({
4951
5266
  }
4952
5267
  )
4953
5268
  ] }),
4954
- /* @__PURE__ */ jsxs13("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4955
- /* @__PURE__ */ jsx15("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
4956
- /* @__PURE__ */ jsx15(
5269
+ /* @__PURE__ */ jsxs15("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5270
+ /* @__PURE__ */ jsx16("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
5271
+ /* @__PURE__ */ jsx16(
4957
5272
  "input",
4958
5273
  {
4959
5274
  type: "text",
@@ -4970,7 +5285,7 @@ function TransitionForm({
4970
5285
  )
4971
5286
  ] })
4972
5287
  ] }),
4973
- /* @__PURE__ */ jsx15(
5288
+ /* @__PURE__ */ jsx16(
4974
5289
  "p",
4975
5290
  {
4976
5291
  style: {
@@ -4990,28 +5305,28 @@ function TransitionForm({
4990
5305
  ]
4991
5306
  }
4992
5307
  ),
4993
- /* @__PURE__ */ jsxs13(
5308
+ /* @__PURE__ */ jsxs15(
4994
5309
  TransitionSection,
4995
5310
  {
4996
5311
  title: messages.inspector.processors,
4997
5312
  testId: "inspector-transition-processes-section",
4998
5313
  children: [
4999
- processorCount === 0 ? /* @__PURE__ */ jsx15("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ jsx15("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
5000
- /* @__PURE__ */ jsx15("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
5001
- processors.map((processor, index) => /* @__PURE__ */ jsxs13("div", { style: processorRowStyle, children: [
5002
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
5003
- /* @__PURE__ */ jsxs13("span", { style: processorOrderStyle, children: [
5314
+ processorCount === 0 ? /* @__PURE__ */ jsx16("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ jsx16("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
5315
+ /* @__PURE__ */ jsx16("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
5316
+ processors.map((processor, index) => /* @__PURE__ */ jsxs15("div", { style: processorRowStyle, children: [
5317
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
5318
+ /* @__PURE__ */ jsxs15("span", { style: processorOrderStyle, children: [
5004
5319
  index + 1,
5005
5320
  "."
5006
5321
  ] }),
5007
- /* @__PURE__ */ jsx15("span", { style: processorTypeChipStyle, children: processor.type }),
5008
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
5009
- /* @__PURE__ */ jsx15("strong", { style: { fontSize: 13 }, children: processor.name }),
5010
- /* @__PURE__ */ jsx15("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
5322
+ /* @__PURE__ */ jsx16("span", { style: processorTypeChipStyle, children: processor.type }),
5323
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
5324
+ /* @__PURE__ */ jsx16("strong", { style: { fontSize: 13 }, children: processor.name }),
5325
+ /* @__PURE__ */ jsx16("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
5011
5326
  ] })
5012
5327
  ] }),
5013
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5014
- /* @__PURE__ */ jsx15(
5328
+ /* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5329
+ /* @__PURE__ */ jsx16(
5015
5330
  "button",
5016
5331
  {
5017
5332
  type: "button",
@@ -5026,7 +5341,7 @@ function TransitionForm({
5026
5341
  children: "Edit"
5027
5342
  }
5028
5343
  ),
5029
- /* @__PURE__ */ jsx15(
5344
+ /* @__PURE__ */ jsx16(
5030
5345
  "button",
5031
5346
  {
5032
5347
  type: "button",
@@ -5037,7 +5352,7 @@ function TransitionForm({
5037
5352
  children: "Duplicate"
5038
5353
  }
5039
5354
  ),
5040
- /* @__PURE__ */ jsx15(
5355
+ /* @__PURE__ */ jsx16(
5041
5356
  "button",
5042
5357
  {
5043
5358
  type: "button",
@@ -5053,7 +5368,7 @@ function TransitionForm({
5053
5368
  children: "Move up"
5054
5369
  }
5055
5370
  ),
5056
- /* @__PURE__ */ jsx15(
5371
+ /* @__PURE__ */ jsx16(
5057
5372
  "button",
5058
5373
  {
5059
5374
  type: "button",
@@ -5069,7 +5384,7 @@ function TransitionForm({
5069
5384
  children: "Move down"
5070
5385
  }
5071
5386
  ),
5072
- /* @__PURE__ */ jsx15(
5387
+ /* @__PURE__ */ jsx16(
5073
5388
  "button",
5074
5389
  {
5075
5390
  type: "button",
@@ -5083,7 +5398,7 @@ function TransitionForm({
5083
5398
  ] })
5084
5399
  ] }, processorUuids[index] ?? `${processor.name}-${index}`))
5085
5400
  ] }),
5086
- /* @__PURE__ */ jsx15(
5401
+ /* @__PURE__ */ jsx16(
5087
5402
  "button",
5088
5403
  {
5089
5404
  type: "button",
@@ -5097,7 +5412,7 @@ function TransitionForm({
5097
5412
  ]
5098
5413
  }
5099
5414
  ),
5100
- /* @__PURE__ */ jsx15(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ jsx15(
5415
+ /* @__PURE__ */ jsx16(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ jsx16(
5101
5416
  AnnotationsField,
5102
5417
  {
5103
5418
  value: transition.annotations,
@@ -5108,7 +5423,7 @@ function TransitionForm({
5108
5423
  onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid } })
5109
5424
  }
5110
5425
  ) }),
5111
- processorModal && /* @__PURE__ */ jsx15(
5426
+ processorModal && /* @__PURE__ */ jsx16(
5112
5427
  ProcessorEditorModal,
5113
5428
  {
5114
5429
  title: processorModal.mode === "add" ? "Add processor" : "Edit processor",
@@ -5128,8 +5443,8 @@ function TransitionSection({
5128
5443
  testId,
5129
5444
  children
5130
5445
  }) {
5131
- return /* @__PURE__ */ jsxs13("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5132
- /* @__PURE__ */ jsx15("header", { style: sectionHeaderStyle, children: title }),
5446
+ return /* @__PURE__ */ jsxs15("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5447
+ /* @__PURE__ */ jsx16("header", { style: sectionHeaderStyle, children: title }),
5133
5448
  children
5134
5449
  ] });
5135
5450
  }
@@ -5138,6 +5453,12 @@ var transitionFormStyle = {
5138
5453
  flexDirection: "column",
5139
5454
  gap: 16
5140
5455
  };
5456
+ var twoColStyle = {
5457
+ display: "grid",
5458
+ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))",
5459
+ gap: 8,
5460
+ alignItems: "end"
5461
+ };
5141
5462
  var transitionSectionStyle = {
5142
5463
  display: "flex",
5143
5464
  flexDirection: "column",
@@ -5236,9 +5557,9 @@ function AnchorSelect({
5236
5557
  { value: "left", label: messages.inspector.anchorLeft },
5237
5558
  { value: "left-bottom", label: messages.inspector.anchorLeftBottom }
5238
5559
  ];
5239
- return /* @__PURE__ */ jsxs13("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5240
- /* @__PURE__ */ jsx15("span", { style: { fontWeight: 500 }, children: label }),
5241
- /* @__PURE__ */ jsx15(
5560
+ return /* @__PURE__ */ jsxs15("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5561
+ /* @__PURE__ */ jsx16("span", { style: { fontWeight: 500 }, children: label }),
5562
+ /* @__PURE__ */ jsx16(
5242
5563
  CustomSelectInput,
5243
5564
  {
5244
5565
  value: value ?? "",
@@ -5253,7 +5574,7 @@ function AnchorSelect({
5253
5574
  }
5254
5575
 
5255
5576
  // src/inspector/Inspector.tsx
5256
- import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
5577
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
5257
5578
  function issueKeyForSelection(selection) {
5258
5579
  if (!selection) return null;
5259
5580
  switch (selection.kind) {
@@ -5293,7 +5614,7 @@ function Inspector({
5293
5614
  return issues.filter((i) => i.targetId === selectionIssueKey);
5294
5615
  }, [issues, selectionIssueKey]);
5295
5616
  const breadcrumb = renderBreadcrumb(resolved);
5296
- return /* @__PURE__ */ jsxs14(
5617
+ return /* @__PURE__ */ jsxs16(
5297
5618
  "aside",
5298
5619
  {
5299
5620
  style: {
@@ -5309,7 +5630,7 @@ function Inspector({
5309
5630
  },
5310
5631
  "data-testid": "inspector",
5311
5632
  children: [
5312
- /* @__PURE__ */ jsxs14(
5633
+ /* @__PURE__ */ jsxs16(
5313
5634
  "header",
5314
5635
  {
5315
5636
  "data-inspector-drag-handle": true,
@@ -5323,8 +5644,8 @@ function Inspector({
5323
5644
  gap: 8
5324
5645
  },
5325
5646
  children: [
5326
- /* @__PURE__ */ jsx16("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5327
- onToggleDock && /* @__PURE__ */ jsx16(
5647
+ /* @__PURE__ */ jsx17("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5648
+ onToggleDock && /* @__PURE__ */ jsx17(
5328
5649
  "button",
5329
5650
  {
5330
5651
  type: "button",
@@ -5349,7 +5670,7 @@ function Inspector({
5349
5670
  children: docked ? "\u2922" : "\u2921"
5350
5671
  }
5351
5672
  ),
5352
- onMinimize && /* @__PURE__ */ jsx16(
5673
+ onMinimize && /* @__PURE__ */ jsx17(
5353
5674
  "button",
5354
5675
  {
5355
5676
  type: "button",
@@ -5375,7 +5696,7 @@ function Inspector({
5375
5696
  children: "\u2013"
5376
5697
  }
5377
5698
  ),
5378
- onClose && /* @__PURE__ */ jsx16(
5699
+ onClose && /* @__PURE__ */ jsx17(
5379
5700
  "button",
5380
5701
  {
5381
5702
  type: "button",
@@ -5403,8 +5724,8 @@ function Inspector({
5403
5724
  ]
5404
5725
  }
5405
5726
  ),
5406
- developerMode && /* @__PURE__ */ jsxs14("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5407
- /* @__PURE__ */ jsx16(
5727
+ developerMode && /* @__PURE__ */ jsxs16("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5728
+ /* @__PURE__ */ jsx17(
5408
5729
  TabButton,
5409
5730
  {
5410
5731
  active: effectiveTab === "properties",
@@ -5413,7 +5734,7 @@ function Inspector({
5413
5734
  children: messages.inspector.properties
5414
5735
  }
5415
5736
  ),
5416
- /* @__PURE__ */ jsx16(
5737
+ /* @__PURE__ */ jsx17(
5417
5738
  TabButton,
5418
5739
  {
5419
5740
  active: effectiveTab === "json",
@@ -5423,11 +5744,11 @@ function Inspector({
5423
5744
  }
5424
5745
  )
5425
5746
  ] }),
5426
- /* @__PURE__ */ jsxs14("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5427
- effectiveTab === "properties" && /* @__PURE__ */ jsxs14(Fragment6, { children: [
5428
- !resolved && /* @__PURE__ */ jsx16(EmptyState, { message: messages.inspector.empty }),
5429
- resolved?.kind === "workflow" && /* @__PURE__ */ jsx16(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5430
- resolved?.kind === "state" && /* @__PURE__ */ jsx16(
5747
+ /* @__PURE__ */ jsxs16("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5748
+ effectiveTab === "properties" && /* @__PURE__ */ jsxs16(Fragment7, { children: [
5749
+ !resolved && /* @__PURE__ */ jsx17(EmptyState, { message: messages.inspector.empty }),
5750
+ resolved?.kind === "workflow" && /* @__PURE__ */ jsx17(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5751
+ resolved?.kind === "state" && /* @__PURE__ */ jsx17(
5431
5752
  StateForm,
5432
5753
  {
5433
5754
  workflow: resolved.workflow,
@@ -5440,7 +5761,7 @@ function Inspector({
5440
5761
  },
5441
5762
  `${resolved.workflow.name}:${resolved.stateCode}`
5442
5763
  ),
5443
- resolved?.kind === "transition" && /* @__PURE__ */ jsx16(
5764
+ resolved?.kind === "transition" && /* @__PURE__ */ jsx17(
5444
5765
  TransitionForm,
5445
5766
  {
5446
5767
  workflow: resolved.workflow,
@@ -5457,7 +5778,7 @@ function Inspector({
5457
5778
  },
5458
5779
  resolved.transitionUuid
5459
5780
  ),
5460
- resolved?.kind === "processor" && /* @__PURE__ */ jsx16(
5781
+ resolved?.kind === "processor" && /* @__PURE__ */ jsx17(
5461
5782
  ProcessorForm,
5462
5783
  {
5463
5784
  processor: resolved.processor,
@@ -5471,8 +5792,8 @@ function Inspector({
5471
5792
  resolved.processorUuid
5472
5793
  )
5473
5794
  ] }),
5474
- developerMode && effectiveTab === "json" && /* @__PURE__ */ jsx16(JsonPreview, { document: doc, resolved }),
5475
- selectionIssues.length > 0 && /* @__PURE__ */ jsx16(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5795
+ developerMode && effectiveTab === "json" && /* @__PURE__ */ jsx17(JsonPreview, { document: doc, resolved }),
5796
+ selectionIssues.length > 0 && /* @__PURE__ */ jsx17(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5476
5797
  ] })
5477
5798
  ]
5478
5799
  }
@@ -5495,7 +5816,7 @@ function TabButton({
5495
5816
  children,
5496
5817
  testId
5497
5818
  }) {
5498
- return /* @__PURE__ */ jsx16(
5819
+ return /* @__PURE__ */ jsx17(
5499
5820
  "button",
5500
5821
  {
5501
5822
  type: "button",
@@ -5516,17 +5837,17 @@ function TabButton({
5516
5837
  );
5517
5838
  }
5518
5839
  function EmptyState({ message }) {
5519
- return /* @__PURE__ */ jsx16("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5840
+ return /* @__PURE__ */ jsx17("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5520
5841
  }
5521
5842
  function IssuesList({
5522
5843
  issues,
5523
5844
  title
5524
5845
  }) {
5525
- return /* @__PURE__ */ jsxs14("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5526
- /* @__PURE__ */ jsx16("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5846
+ return /* @__PURE__ */ jsxs16("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5847
+ /* @__PURE__ */ jsx17("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5527
5848
  issues.map((issue, i) => {
5528
5849
  const tone = severityTone(issue.severity);
5529
- return /* @__PURE__ */ jsxs14(
5850
+ return /* @__PURE__ */ jsxs16(
5530
5851
  "div",
5531
5852
  {
5532
5853
  style: {
@@ -5537,8 +5858,8 @@ function IssuesList({
5537
5858
  fontSize: 12
5538
5859
  },
5539
5860
  children: [
5540
- /* @__PURE__ */ jsx16("strong", { children: issue.code }),
5541
- /* @__PURE__ */ jsx16("div", { children: issue.message })
5861
+ /* @__PURE__ */ jsx17("strong", { children: issue.code }),
5862
+ /* @__PURE__ */ jsx17("div", { children: issue.message })
5542
5863
  ]
5543
5864
  },
5544
5865
  `${issue.code}-${i}`
@@ -5558,7 +5879,7 @@ function JsonPreview({
5558
5879
  if (resolved.kind === "processor") return JSON.stringify(resolved.processor, null, 2);
5559
5880
  return "";
5560
5881
  }, [doc, resolved]);
5561
- return /* @__PURE__ */ jsx16(
5882
+ return /* @__PURE__ */ jsx17(
5562
5883
  "pre",
5563
5884
  {
5564
5885
  style: {
@@ -5616,7 +5937,7 @@ function savePlacement(base, p) {
5616
5937
  }
5617
5938
 
5618
5939
  // src/inspector/InspectorFrame.tsx
5619
- import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
5940
+ import { Fragment as Fragment8, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
5620
5941
  var FLOATING_Z = 40;
5621
5942
  var MIN_BAR_Z = 50;
5622
5943
  function InspectorFrame({
@@ -5684,8 +6005,8 @@ function InspectorFrame({
5684
6005
  overflow: "hidden",
5685
6006
  display: minimized ? "none" : "flex"
5686
6007
  } : { position: "relative", flex: `0 0 ${dockedWidth}px`, width: dockedWidth, height: "100%", display: "flex" };
5687
- return /* @__PURE__ */ jsxs15(Fragment7, { children: [
5688
- mode === "docked" && /* @__PURE__ */ jsx17(
6008
+ return /* @__PURE__ */ jsxs17(Fragment8, { children: [
6009
+ mode === "docked" && /* @__PURE__ */ jsx18(
5689
6010
  "div",
5690
6011
  {
5691
6012
  "data-testid": "inspector-resize-handle",
@@ -5695,7 +6016,7 @@ function InspectorFrame({
5695
6016
  onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
5696
6017
  }
5697
6018
  ),
5698
- /* @__PURE__ */ jsxs15(
6019
+ /* @__PURE__ */ jsxs17(
5699
6020
  "div",
5700
6021
  {
5701
6022
  "data-testid": "inspector-frame",
@@ -5703,7 +6024,7 @@ function InspectorFrame({
5703
6024
  style,
5704
6025
  children: [
5705
6026
  children,
5706
- floating && /* @__PURE__ */ jsx17(
6027
+ floating && /* @__PURE__ */ jsx18(
5707
6028
  "div",
5708
6029
  {
5709
6030
  "data-testid": "inspector-resize-grip",
@@ -5714,7 +6035,7 @@ function InspectorFrame({
5714
6035
  ]
5715
6036
  }
5716
6037
  ),
5717
- minimized && /* @__PURE__ */ jsxs15(
6038
+ minimized && /* @__PURE__ */ jsxs17(
5718
6039
  "div",
5719
6040
  {
5720
6041
  "data-testid": "inspector-min-bar",
@@ -5722,9 +6043,9 @@ function InspectorFrame({
5722
6043
  title: messages.inspector.restore,
5723
6044
  style: minBarStyle,
5724
6045
  children: [
5725
- /* @__PURE__ */ jsx17("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colors.primary, flex: "0 0 auto" } }),
5726
- /* @__PURE__ */ jsx17("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12, color: colors.textSecondary }, children: messages.inspector.minimizedTitle }),
5727
- /* @__PURE__ */ jsx17(
6046
+ /* @__PURE__ */ jsx18("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colors.primary, flex: "0 0 auto" } }),
6047
+ /* @__PURE__ */ jsx18("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12, color: colors.textSecondary }, children: messages.inspector.minimizedTitle }),
6048
+ /* @__PURE__ */ jsx18(
5728
6049
  "button",
5729
6050
  {
5730
6051
  type: "button",
@@ -5739,7 +6060,7 @@ function InspectorFrame({
5739
6060
  children: "\u2922"
5740
6061
  }
5741
6062
  ),
5742
- onClose && /* @__PURE__ */ jsx17(
6063
+ onClose && /* @__PURE__ */ jsx18(
5743
6064
  "button",
5744
6065
  {
5745
6066
  type: "button",
@@ -5794,7 +6115,7 @@ var barBtnStyle = {
5794
6115
  };
5795
6116
 
5796
6117
  // src/toolbar/Toolbar.tsx
5797
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
6118
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
5798
6119
  function Toolbar({
5799
6120
  derived,
5800
6121
  readOnly,
@@ -5808,7 +6129,7 @@ function Toolbar({
5808
6129
  toolbarEnd
5809
6130
  }) {
5810
6131
  const messages = useMessages();
5811
- return /* @__PURE__ */ jsxs16(
6132
+ return /* @__PURE__ */ jsxs18(
5812
6133
  "footer",
5813
6134
  {
5814
6135
  style: {
@@ -5823,11 +6144,11 @@ function Toolbar({
5823
6144
  },
5824
6145
  "data-testid": "toolbar",
5825
6146
  children: [
5826
- toolbarStart && /* @__PURE__ */ jsx18("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
5827
- toolbarCenter && /* @__PURE__ */ jsx18("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
5828
- !toolbarCenter && /* @__PURE__ */ jsx18("div", { style: { flex: 1 } }),
5829
- /* @__PURE__ */ jsxs16("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
5830
- /* @__PURE__ */ jsx18(
6147
+ toolbarStart && /* @__PURE__ */ jsx19("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
6148
+ toolbarCenter && /* @__PURE__ */ jsx19("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
6149
+ !toolbarCenter && /* @__PURE__ */ jsx19("div", { style: { flex: 1 } }),
6150
+ /* @__PURE__ */ jsxs18("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
6151
+ /* @__PURE__ */ jsx19(
5831
6152
  ValidationPill,
5832
6153
  {
5833
6154
  severity: "error",
@@ -5839,7 +6160,7 @@ function Toolbar({
5839
6160
  testId: "toolbar-errors"
5840
6161
  }
5841
6162
  ),
5842
- /* @__PURE__ */ jsx18(
6163
+ /* @__PURE__ */ jsx19(
5843
6164
  ValidationPill,
5844
6165
  {
5845
6166
  severity: "warning",
@@ -5851,7 +6172,7 @@ function Toolbar({
5851
6172
  testId: "toolbar-warnings"
5852
6173
  }
5853
6174
  ),
5854
- /* @__PURE__ */ jsx18(
6175
+ /* @__PURE__ */ jsx19(
5855
6176
  ValidationPill,
5856
6177
  {
5857
6178
  severity: "info",
@@ -5864,7 +6185,7 @@ function Toolbar({
5864
6185
  }
5865
6186
  )
5866
6187
  ] }),
5867
- onSave && showSaveButton && /* @__PURE__ */ jsx18(
6188
+ onSave && showSaveButton && /* @__PURE__ */ jsx19(
5868
6189
  "button",
5869
6190
  {
5870
6191
  type: "button",
@@ -5875,7 +6196,7 @@ function Toolbar({
5875
6196
  children: messages.toolbar.save
5876
6197
  }
5877
6198
  ),
5878
- toolbarEnd && /* @__PURE__ */ jsx18("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
6199
+ toolbarEnd && /* @__PURE__ */ jsx19("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5879
6200
  ]
5880
6201
  }
5881
6202
  );
@@ -5897,7 +6218,7 @@ function ValidationPill({
5897
6218
  const tone = severityTone(severity);
5898
6219
  const interactive = count > 0 && !!onClick;
5899
6220
  const hasIssues = count > 0;
5900
- return /* @__PURE__ */ jsxs16(
6221
+ return /* @__PURE__ */ jsxs18(
5901
6222
  "button",
5902
6223
  {
5903
6224
  type: "button",
@@ -5924,7 +6245,7 @@ function ValidationPill({
5924
6245
  height: 20
5925
6246
  },
5926
6247
  children: [
5927
- /* @__PURE__ */ jsx18("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
6248
+ /* @__PURE__ */ jsx19("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5928
6249
  count
5929
6250
  ]
5930
6251
  }
@@ -5949,7 +6270,7 @@ var slotStyle = {
5949
6270
 
5950
6271
  // src/toolbar/IssuesDrawer.tsx
5951
6272
  import { useEffect as useEffect8, useMemo as useMemo5, useRef as useRef10 } from "react";
5952
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
6273
+ import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
5953
6274
  function resolveTarget(doc, targetId) {
5954
6275
  if (!targetId) return null;
5955
6276
  const ids = doc.meta.ids;
@@ -6038,7 +6359,7 @@ function IssuesDrawer({
6038
6359
  }, [severity, messages]);
6039
6360
  const tone = severityTone(severity);
6040
6361
  if (!open) return null;
6041
- return /* @__PURE__ */ jsxs17(
6362
+ return /* @__PURE__ */ jsxs19(
6042
6363
  "div",
6043
6364
  {
6044
6365
  ref,
@@ -6062,7 +6383,7 @@ function IssuesDrawer({
6062
6383
  flexDirection: "column"
6063
6384
  },
6064
6385
  children: [
6065
- /* @__PURE__ */ jsxs17(
6386
+ /* @__PURE__ */ jsxs19(
6066
6387
  "header",
6067
6388
  {
6068
6389
  style: {
@@ -6073,7 +6394,7 @@ function IssuesDrawer({
6073
6394
  gap: 8
6074
6395
  },
6075
6396
  children: [
6076
- /* @__PURE__ */ jsx19(
6397
+ /* @__PURE__ */ jsx20(
6077
6398
  "span",
6078
6399
  {
6079
6400
  style: {
@@ -6086,12 +6407,12 @@ function IssuesDrawer({
6086
6407
  "aria-hidden": true
6087
6408
  }
6088
6409
  ),
6089
- /* @__PURE__ */ jsxs17("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6410
+ /* @__PURE__ */ jsxs19("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6090
6411
  title,
6091
6412
  " \xB7 ",
6092
6413
  filtered.length
6093
6414
  ] }),
6094
- /* @__PURE__ */ jsx19(
6415
+ /* @__PURE__ */ jsx20(
6095
6416
  "button",
6096
6417
  {
6097
6418
  type: "button",
@@ -6114,14 +6435,14 @@ function IssuesDrawer({
6114
6435
  ]
6115
6436
  }
6116
6437
  ),
6117
- filtered.length === 0 ? /* @__PURE__ */ jsx19(
6438
+ filtered.length === 0 ? /* @__PURE__ */ jsx20(
6118
6439
  "p",
6119
6440
  {
6120
6441
  style: { padding: 12, color: colors.textTertiary, fontSize: 12, margin: 0 },
6121
6442
  "data-testid": "issues-drawer-empty",
6122
6443
  children: messages.issues.none
6123
6444
  }
6124
- ) : /* @__PURE__ */ jsx19(
6445
+ ) : /* @__PURE__ */ jsx20(
6125
6446
  "ul",
6126
6447
  {
6127
6448
  style: {
@@ -6135,7 +6456,7 @@ function IssuesDrawer({
6135
6456
  children: filtered.map((issue, idx) => {
6136
6457
  const target = resolveTarget(doc, issue.targetId);
6137
6458
  const targetLabel = target ? target.kind === "transition" ? `${messages.issues.relatedTransition}: ${target.label}` : target.kind === "state" ? `${messages.issues.relatedState}: ${target.label}` : target.label : null;
6138
- return /* @__PURE__ */ jsxs17(
6459
+ return /* @__PURE__ */ jsxs19(
6139
6460
  "li",
6140
6461
  {
6141
6462
  style: {
@@ -6149,10 +6470,10 @@ function IssuesDrawer({
6149
6470
  },
6150
6471
  "data-testid": `issues-drawer-item-${idx}`,
6151
6472
  children: [
6152
- /* @__PURE__ */ jsx19("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
6153
- /* @__PURE__ */ jsx19("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
6154
- targetLabel && /* @__PURE__ */ jsx19("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
6155
- target && /* @__PURE__ */ jsx19("div", { children: /* @__PURE__ */ jsx19(
6473
+ /* @__PURE__ */ jsx20("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
6474
+ /* @__PURE__ */ jsx20("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
6475
+ targetLabel && /* @__PURE__ */ jsx20("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
6476
+ target && /* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20(
6156
6477
  "button",
6157
6478
  {
6158
6479
  type: "button",
@@ -6192,7 +6513,7 @@ import { useEffect as useEffect10, useRef as useRef12, useState as useState13 }
6192
6513
  // src/toolbar/VersionBadge.tsx
6193
6514
  import { useEffect as useEffect9, useRef as useRef11, useState as useState12 } from "react";
6194
6515
  import { createPortal as createPortal2 } from "react-dom";
6195
- import { Fragment as Fragment8, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
6516
+ import { Fragment as Fragment9, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
6196
6517
  function VersionBadge({
6197
6518
  version,
6198
6519
  supportedVersions,
@@ -6225,7 +6546,7 @@ function VersionBadge({
6225
6546
  setOpen((o) => !o);
6226
6547
  };
6227
6548
  if (readOnly) {
6228
- return /* @__PURE__ */ jsx20(
6549
+ return /* @__PURE__ */ jsx21(
6229
6550
  "div",
6230
6551
  {
6231
6552
  "data-testid": "version-badge",
@@ -6244,7 +6565,7 @@ function VersionBadge({
6244
6565
  );
6245
6566
  }
6246
6567
  const dropdown = open && dropdownPos ? createPortal2(
6247
- /* @__PURE__ */ jsxs18(
6568
+ /* @__PURE__ */ jsxs20(
6248
6569
  "div",
6249
6570
  {
6250
6571
  ref: dropdownRef,
@@ -6263,7 +6584,7 @@ function VersionBadge({
6263
6584
  zIndex: 9999
6264
6585
  },
6265
6586
  children: [
6266
- /* @__PURE__ */ jsx20(
6587
+ /* @__PURE__ */ jsx21(
6267
6588
  "div",
6268
6589
  {
6269
6590
  style: {
@@ -6280,7 +6601,7 @@ function VersionBadge({
6280
6601
  ),
6281
6602
  [...supportedVersions].reverse().map((v) => {
6282
6603
  const isCurrent = v === version.replace(/^v/, "");
6283
- return /* @__PURE__ */ jsxs18(
6604
+ return /* @__PURE__ */ jsxs20(
6284
6605
  "button",
6285
6606
  {
6286
6607
  type: "button",
@@ -6303,16 +6624,16 @@ function VersionBadge({
6303
6624
  textAlign: "left"
6304
6625
  },
6305
6626
  children: [
6306
- /* @__PURE__ */ jsxs18("span", { children: [
6627
+ /* @__PURE__ */ jsxs20("span", { children: [
6307
6628
  v,
6308
6629
  " ",
6309
- /* @__PURE__ */ jsxs18("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6630
+ /* @__PURE__ */ jsxs20("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6310
6631
  "cyoda-go ",
6311
6632
  v,
6312
6633
  ".x"
6313
6634
  ] })
6314
6635
  ] }),
6315
- isCurrent && /* @__PURE__ */ jsx20(
6636
+ isCurrent && /* @__PURE__ */ jsx21(
6316
6637
  "span",
6317
6638
  {
6318
6639
  style: {
@@ -6336,8 +6657,8 @@ function VersionBadge({
6336
6657
  ),
6337
6658
  document.body
6338
6659
  ) : null;
6339
- return /* @__PURE__ */ jsxs18(Fragment8, { children: [
6340
- /* @__PURE__ */ jsxs18(
6660
+ return /* @__PURE__ */ jsxs20(Fragment9, { children: [
6661
+ /* @__PURE__ */ jsxs20(
6341
6662
  "button",
6342
6663
  {
6343
6664
  ref: buttonRef,
@@ -6360,7 +6681,7 @@ function VersionBadge({
6360
6681
  },
6361
6682
  children: [
6362
6683
  version,
6363
- /* @__PURE__ */ jsx20("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6684
+ /* @__PURE__ */ jsx21("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6364
6685
  ]
6365
6686
  }
6366
6687
  ),
@@ -6369,7 +6690,7 @@ function VersionBadge({
6369
6690
  }
6370
6691
 
6371
6692
  // src/toolbar/WorkflowTabs.tsx
6372
- import { Fragment as Fragment9, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
6693
+ import { Fragment as Fragment10, jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
6373
6694
  function WorkflowTabs({
6374
6695
  workflows,
6375
6696
  activeWorkflow,
@@ -6406,7 +6727,7 @@ function WorkflowTabs({
6406
6727
  setEditingTab(null);
6407
6728
  };
6408
6729
  const cancelEdit = () => setEditingTab(null);
6409
- return /* @__PURE__ */ jsxs19(
6730
+ return /* @__PURE__ */ jsxs21(
6410
6731
  "nav",
6411
6732
  {
6412
6733
  style: {
@@ -6424,7 +6745,7 @@ function WorkflowTabs({
6424
6745
  workflows.map((w) => {
6425
6746
  const active = w.name === activeWorkflow;
6426
6747
  const isEditing = editingTab === w.name;
6427
- return /* @__PURE__ */ jsxs19(
6748
+ return /* @__PURE__ */ jsxs21(
6428
6749
  "div",
6429
6750
  {
6430
6751
  style: {
@@ -6435,7 +6756,7 @@ function WorkflowTabs({
6435
6756
  background: active ? "white" : "transparent"
6436
6757
  },
6437
6758
  children: [
6438
- isEditing ? /* @__PURE__ */ jsx21(
6759
+ isEditing ? /* @__PURE__ */ jsx22(
6439
6760
  "input",
6440
6761
  {
6441
6762
  ref: inputRef,
@@ -6466,7 +6787,7 @@ function WorkflowTabs({
6466
6787
  width: Math.max(60, draftName.length * 8)
6467
6788
  }
6468
6789
  }
6469
- ) : /* @__PURE__ */ jsx21(
6790
+ ) : /* @__PURE__ */ jsx22(
6470
6791
  "button",
6471
6792
  {
6472
6793
  type: "button",
@@ -6485,7 +6806,7 @@ function WorkflowTabs({
6485
6806
  children: w.name || messages.tabs.untitled
6486
6807
  }
6487
6808
  ),
6488
- onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ jsx21(
6809
+ onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ jsx22(
6489
6810
  "button",
6490
6811
  {
6491
6812
  type: "button",
@@ -6508,7 +6829,7 @@ function WorkflowTabs({
6508
6829
  w.name
6509
6830
  );
6510
6831
  }),
6511
- onAdd && !readOnly && /* @__PURE__ */ jsxs19(
6832
+ onAdd && !readOnly && /* @__PURE__ */ jsxs21(
6512
6833
  "button",
6513
6834
  {
6514
6835
  type: "button",
@@ -6533,9 +6854,9 @@ function WorkflowTabs({
6533
6854
  ]
6534
6855
  }
6535
6856
  ),
6536
- dialectVersion && /* @__PURE__ */ jsxs19(Fragment9, { children: [
6537
- /* @__PURE__ */ jsx21("div", { style: { flex: 1 } }),
6538
- /* @__PURE__ */ jsx21(
6857
+ dialectVersion && /* @__PURE__ */ jsxs21(Fragment10, { children: [
6858
+ /* @__PURE__ */ jsx22("div", { style: { flex: 1 } }),
6859
+ /* @__PURE__ */ jsx22(
6539
6860
  VersionBadge,
6540
6861
  {
6541
6862
  version: dialectVersion,
@@ -6553,7 +6874,7 @@ function WorkflowTabs({
6553
6874
  // src/modals/DragConnectModal.tsx
6554
6875
  import { useState as useState14 } from "react";
6555
6876
  import { NAME_REGEX as NAME_REGEX4 } from "@cyoda/workflow-core";
6556
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
6877
+ import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
6557
6878
  function generateDefault(toState, existing) {
6558
6879
  const base = `to_${toState}`;
6559
6880
  if (!existing.has(base)) return base;
@@ -6574,16 +6895,16 @@ function DragConnectModal({
6574
6895
  const invalidFormat = !!name && !NAME_REGEX4.test(name);
6575
6896
  const duplicate = existing.has(name);
6576
6897
  const blocked = name.length === 0 || invalidFormat || duplicate;
6577
- return /* @__PURE__ */ jsxs20(ModalFrame, { onCancel, children: [
6578
- /* @__PURE__ */ jsx22("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6579
- /* @__PURE__ */ jsxs20("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6898
+ return /* @__PURE__ */ jsxs22(ModalFrame, { onCancel, children: [
6899
+ /* @__PURE__ */ jsx23("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6900
+ /* @__PURE__ */ jsxs22("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6580
6901
  fromState,
6581
6902
  " \u2192 ",
6582
6903
  toState
6583
6904
  ] }),
6584
- /* @__PURE__ */ jsxs20("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6585
- /* @__PURE__ */ jsx22("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6586
- /* @__PURE__ */ jsx22(
6905
+ /* @__PURE__ */ jsxs22("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6906
+ /* @__PURE__ */ jsx23("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6907
+ /* @__PURE__ */ jsx23(
6587
6908
  "input",
6588
6909
  {
6589
6910
  type: "text",
@@ -6603,11 +6924,11 @@ function DragConnectModal({
6603
6924
  }
6604
6925
  )
6605
6926
  ] }),
6606
- invalidFormat && /* @__PURE__ */ jsx22("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6607
- duplicate && /* @__PURE__ */ jsx22("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6608
- /* @__PURE__ */ jsxs20("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6609
- /* @__PURE__ */ jsx22("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6610
- /* @__PURE__ */ jsx22(
6927
+ invalidFormat && /* @__PURE__ */ jsx23("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6928
+ duplicate && /* @__PURE__ */ jsx23("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6929
+ /* @__PURE__ */ jsxs22("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6930
+ /* @__PURE__ */ jsx23("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6931
+ /* @__PURE__ */ jsx23(
6611
6932
  "button",
6612
6933
  {
6613
6934
  type: "button",
@@ -6644,7 +6965,7 @@ var primaryBtn3 = {
6644
6965
  // src/modals/AddStateModal.tsx
6645
6966
  import { useEffect as useEffect11, useRef as useRef13, useState as useState15 } from "react";
6646
6967
  import { NAME_REGEX as NAME_REGEX5 } from "@cyoda/workflow-core";
6647
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
6968
+ import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
6648
6969
  function generateName(existing) {
6649
6970
  let n = 1;
6650
6971
  while (existing.includes(`state${n}`)) n++;
@@ -6672,11 +6993,11 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6672
6993
  }
6673
6994
  onCreate(name.trim());
6674
6995
  };
6675
- return /* @__PURE__ */ jsxs21(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6676
- /* @__PURE__ */ jsx23("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6677
- /* @__PURE__ */ jsxs21("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6678
- /* @__PURE__ */ jsx23("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6679
- /* @__PURE__ */ jsx23(
6996
+ return /* @__PURE__ */ jsxs23(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6997
+ /* @__PURE__ */ jsx24("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6998
+ /* @__PURE__ */ jsxs23("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6999
+ /* @__PURE__ */ jsx24("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
7000
+ /* @__PURE__ */ jsx24(
6680
7001
  "input",
6681
7002
  {
6682
7003
  ref: inputRef,
@@ -6702,7 +7023,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6702
7023
  }
6703
7024
  }
6704
7025
  ),
6705
- error && /* @__PURE__ */ jsx23(
7026
+ error && /* @__PURE__ */ jsx24(
6706
7027
  "div",
6707
7028
  {
6708
7029
  id: "add-state-error",
@@ -6712,8 +7033,8 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6712
7033
  }
6713
7034
  )
6714
7035
  ] }),
6715
- /* @__PURE__ */ jsxs21("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6716
- /* @__PURE__ */ jsx23(
7036
+ /* @__PURE__ */ jsxs23("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
7037
+ /* @__PURE__ */ jsx24(
6717
7038
  "button",
6718
7039
  {
6719
7040
  type: "button",
@@ -6723,7 +7044,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6723
7044
  children: "Cancel"
6724
7045
  }
6725
7046
  ),
6726
- /* @__PURE__ */ jsx23(
7047
+ /* @__PURE__ */ jsx24(
6727
7048
  "button",
6728
7049
  {
6729
7050
  type: "button",
@@ -6753,15 +7074,15 @@ var primaryBtn4 = {
6753
7074
 
6754
7075
  // src/modals/HelpModal.tsx
6755
7076
  import { workflowPalette as workflowPalette5 } from "@cyoda/workflow-viewer/theme";
6756
- import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
7077
+ import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
6757
7078
  function HelpModal({ onCancel }) {
6758
7079
  const messages = useMessages();
6759
7080
  const h = messages.help;
6760
7081
  const node = workflowPalette5.node;
6761
7082
  const edge = workflowPalette5.edge;
6762
- return /* @__PURE__ */ jsx24(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ jsxs22("div", { style: { width: 480, maxWidth: "85vw" }, children: [
6763
- /* @__PURE__ */ jsx24("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
6764
- /* @__PURE__ */ jsxs22(
7083
+ return /* @__PURE__ */ jsx25(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ jsxs24("div", { style: { width: 480, maxWidth: "85vw" }, children: [
7084
+ /* @__PURE__ */ jsx25("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
7085
+ /* @__PURE__ */ jsxs24(
6765
7086
  "div",
6766
7087
  {
6767
7088
  style: {
@@ -6774,48 +7095,46 @@ function HelpModal({ onCancel }) {
6774
7095
  gap: 16
6775
7096
  },
6776
7097
  children: [
6777
- /* @__PURE__ */ jsxs22(Section, { title: h.statesTitle, children: [
6778
- /* @__PURE__ */ jsx24(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
6779
- /* @__PURE__ */ jsx24(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
6780
- /* @__PURE__ */ jsx24(ColorRow, { fill: node.processing.fill, border: node.processing.border, label: h.stateProcessing }),
6781
- /* @__PURE__ */ jsx24(ColorRow, { fill: node.manualReview.fill, border: node.manualReview.border, label: h.stateManualReview }),
6782
- /* @__PURE__ */ jsx24(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
6783
- /* @__PURE__ */ jsx24(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
6784
- /* @__PURE__ */ jsx24(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
7098
+ /* @__PURE__ */ jsxs24(Section, { title: h.statesTitle, children: [
7099
+ /* @__PURE__ */ jsx25(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
7100
+ /* @__PURE__ */ jsx25(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
7101
+ /* @__PURE__ */ jsx25(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
7102
+ /* @__PURE__ */ jsx25(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
7103
+ /* @__PURE__ */ jsx25(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
6785
7104
  ] }),
6786
- /* @__PURE__ */ jsxs22(Section, { title: h.transitionsTitle, children: [
6787
- /* @__PURE__ */ jsx24(LineRow, { color: edge.automated, label: h.transitionAutomated }),
6788
- /* @__PURE__ */ jsx24(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
6789
- /* @__PURE__ */ jsx24(LineRow, { color: edge.conditional, label: h.transitionConditional }),
6790
- /* @__PURE__ */ jsx24(LineRow, { color: edge.processing, label: h.transitionProcessing }),
6791
- /* @__PURE__ */ jsx24(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
6792
- /* @__PURE__ */ jsx24(LineRow, { color: edge.loop, label: h.transitionLoop }),
6793
- /* @__PURE__ */ jsx24(LineRow, { color: edge.disabled, label: h.transitionDisabled })
7105
+ /* @__PURE__ */ jsxs24(Section, { title: h.transitionsTitle, children: [
7106
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.automated, label: h.transitionAutomated }),
7107
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
7108
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.conditional, label: h.transitionConditional }),
7109
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.processing, label: h.transitionProcessing }),
7110
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
7111
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.loop, label: h.transitionLoop }),
7112
+ /* @__PURE__ */ jsx25(LineRow, { color: edge.disabled, label: h.transitionDisabled })
6794
7113
  ] }),
6795
- /* @__PURE__ */ jsxs22(Section, { title: h.controlsTitle, children: [
6796
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
6797
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
6798
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
6799
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
6800
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
6801
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
6802
- /* @__PURE__ */ jsx24(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
7114
+ /* @__PURE__ */ jsxs24(Section, { title: h.controlsTitle, children: [
7115
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
7116
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
7117
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
7118
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
7119
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
7120
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
7121
+ /* @__PURE__ */ jsx25(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
6803
7122
  ] }),
6804
- /* @__PURE__ */ jsx24(Section, { title: h.tipsTitle, children: /* @__PURE__ */ jsxs22("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
6805
- /* @__PURE__ */ jsx24("li", { children: h.tipDoubleClick }),
6806
- /* @__PURE__ */ jsx24("li", { children: h.tipConnect }),
6807
- /* @__PURE__ */ jsx24("li", { children: h.tipSelect }),
6808
- /* @__PURE__ */ jsx24("li", { children: h.tipMove })
7123
+ /* @__PURE__ */ jsx25(Section, { title: h.tipsTitle, children: /* @__PURE__ */ jsxs24("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
7124
+ /* @__PURE__ */ jsx25("li", { children: h.tipDoubleClick }),
7125
+ /* @__PURE__ */ jsx25("li", { children: h.tipConnect }),
7126
+ /* @__PURE__ */ jsx25("li", { children: h.tipSelect }),
7127
+ /* @__PURE__ */ jsx25("li", { children: h.tipMove })
6809
7128
  ] }) })
6810
7129
  ]
6811
7130
  }
6812
7131
  ),
6813
- /* @__PURE__ */ jsx24("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ jsx24("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
7132
+ /* @__PURE__ */ jsx25("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ jsx25("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
6814
7133
  ] }) });
6815
7134
  }
6816
7135
  function Section({ title, children }) {
6817
- return /* @__PURE__ */ jsxs22("div", { children: [
6818
- /* @__PURE__ */ jsx24(
7136
+ return /* @__PURE__ */ jsxs24("div", { children: [
7137
+ /* @__PURE__ */ jsx25(
6819
7138
  "h3",
6820
7139
  {
6821
7140
  style: {
@@ -6829,12 +7148,12 @@ function Section({ title, children }) {
6829
7148
  children: title
6830
7149
  }
6831
7150
  ),
6832
- /* @__PURE__ */ jsx24("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
7151
+ /* @__PURE__ */ jsx25("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6833
7152
  ] });
6834
7153
  }
6835
7154
  function ColorRow({ fill, border, label }) {
6836
- return /* @__PURE__ */ jsxs22("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6837
- /* @__PURE__ */ jsx24(
7155
+ return /* @__PURE__ */ jsxs24("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7156
+ /* @__PURE__ */ jsx25(
6838
7157
  "span",
6839
7158
  {
6840
7159
  style: {
@@ -6847,12 +7166,12 @@ function ColorRow({ fill, border, label }) {
6847
7166
  }
6848
7167
  }
6849
7168
  ),
6850
- /* @__PURE__ */ jsx24("span", { children: label })
7169
+ /* @__PURE__ */ jsx25("span", { children: label })
6851
7170
  ] });
6852
7171
  }
6853
7172
  function LineRow({ color, label, dashed }) {
6854
- return /* @__PURE__ */ jsxs22("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6855
- /* @__PURE__ */ jsx24("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ jsx24(
7173
+ return /* @__PURE__ */ jsxs24("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7174
+ /* @__PURE__ */ jsx25("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ jsx25(
6856
7175
  "line",
6857
7176
  {
6858
7177
  x1: "2",
@@ -6865,12 +7184,12 @@ function LineRow({ color, label, dashed }) {
6865
7184
  ...dashed ? { strokeDasharray: "3 3" } : {}
6866
7185
  }
6867
7186
  ) }),
6868
- /* @__PURE__ */ jsx24("span", { children: label })
7187
+ /* @__PURE__ */ jsx25("span", { children: label })
6869
7188
  ] });
6870
7189
  }
6871
7190
  function ShortcutRow({ keys, label }) {
6872
- return /* @__PURE__ */ jsxs22("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6873
- /* @__PURE__ */ jsx24(
7191
+ return /* @__PURE__ */ jsxs24("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
7192
+ /* @__PURE__ */ jsx25(
6874
7193
  "kbd",
6875
7194
  {
6876
7195
  style: {
@@ -6890,12 +7209,12 @@ function ShortcutRow({ keys, label }) {
6890
7209
  children: keys
6891
7210
  }
6892
7211
  ),
6893
- /* @__PURE__ */ jsx24("span", { children: label })
7212
+ /* @__PURE__ */ jsx25("span", { children: label })
6894
7213
  ] });
6895
7214
  }
6896
7215
 
6897
7216
  // src/modals/VersionSwitchModal.tsx
6898
- import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
7217
+ import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
6899
7218
  function VersionSwitchModal({
6900
7219
  fromVersion,
6901
7220
  toVersion,
@@ -6903,7 +7222,7 @@ function VersionSwitchModal({
6903
7222
  onConfirm,
6904
7223
  onCancel
6905
7224
  }) {
6906
- return /* @__PURE__ */ jsx25(
7225
+ return /* @__PURE__ */ jsx26(
6907
7226
  "div",
6908
7227
  {
6909
7228
  style: {
@@ -6915,7 +7234,7 @@ function VersionSwitchModal({
6915
7234
  justifyContent: "center",
6916
7235
  zIndex: 1e3
6917
7236
  },
6918
- children: /* @__PURE__ */ jsxs23(
7237
+ children: /* @__PURE__ */ jsxs25(
6919
7238
  "div",
6920
7239
  {
6921
7240
  "data-testid": "version-switch-modal",
@@ -6929,8 +7248,8 @@ function VersionSwitchModal({
6929
7248
  fontFamily: "inherit"
6930
7249
  },
6931
7250
  children: [
6932
- /* @__PURE__ */ jsxs23("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6933
- /* @__PURE__ */ jsx25(
7251
+ /* @__PURE__ */ jsxs25("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
7252
+ /* @__PURE__ */ jsx26(
6934
7253
  "div",
6935
7254
  {
6936
7255
  style: {
@@ -6947,20 +7266,20 @@ function VersionSwitchModal({
6947
7266
  children: "\u26A0\uFE0F"
6948
7267
  }
6949
7268
  ),
6950
- /* @__PURE__ */ jsxs23("div", { children: [
6951
- /* @__PURE__ */ jsxs23("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
7269
+ /* @__PURE__ */ jsxs25("div", { children: [
7270
+ /* @__PURE__ */ jsxs25("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6952
7271
  "Switch to ",
6953
7272
  toVersion,
6954
7273
  "?"
6955
7274
  ] }),
6956
- /* @__PURE__ */ jsxs23("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
7275
+ /* @__PURE__ */ jsxs25("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6957
7276
  "Switching to ",
6958
7277
  toVersion,
6959
7278
  " will remove data not supported in that dialect:"
6960
7279
  ] })
6961
7280
  ] })
6962
7281
  ] }),
6963
- /* @__PURE__ */ jsxs23(
7282
+ /* @__PURE__ */ jsxs25(
6964
7283
  "div",
6965
7284
  {
6966
7285
  style: {
@@ -6973,17 +7292,17 @@ function VersionSwitchModal({
6973
7292
  fontSize: 12
6974
7293
  },
6975
7294
  children: [
6976
- /* @__PURE__ */ jsx25("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
6977
- /* @__PURE__ */ jsx25("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ jsx25("li", { children: w }, i)) })
7295
+ /* @__PURE__ */ jsx26("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
7296
+ /* @__PURE__ */ jsx26("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ jsx26("li", { children: w }, i)) })
6978
7297
  ]
6979
7298
  }
6980
7299
  ),
6981
- /* @__PURE__ */ jsxs23("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
7300
+ /* @__PURE__ */ jsxs25("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6982
7301
  "This cannot be undone. You can switch back to ",
6983
7302
  fromVersion,
6984
7303
  " any time, but the removed data will not be restored."
6985
7304
  ] }),
6986
- /* @__PURE__ */ jsxs23(
7305
+ /* @__PURE__ */ jsxs25(
6987
7306
  "div",
6988
7307
  {
6989
7308
  style: {
@@ -6995,7 +7314,7 @@ function VersionSwitchModal({
6995
7314
  marginTop: 16
6996
7315
  },
6997
7316
  children: [
6998
- /* @__PURE__ */ jsx25(
7317
+ /* @__PURE__ */ jsx26(
6999
7318
  "button",
7000
7319
  {
7001
7320
  type: "button",
@@ -7013,7 +7332,7 @@ function VersionSwitchModal({
7013
7332
  children: "Cancel"
7014
7333
  }
7015
7334
  ),
7016
- /* @__PURE__ */ jsxs23(
7335
+ /* @__PURE__ */ jsxs25(
7017
7336
  "button",
7018
7337
  {
7019
7338
  type: "button",
@@ -7048,7 +7367,7 @@ function VersionSwitchModal({
7048
7367
 
7049
7368
  // src/components/CommentNode.tsx
7050
7369
  import { useRef as useRef14, useState as useState16 } from "react";
7051
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
7370
+ import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
7052
7371
  function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7053
7372
  const [editing, setEditing] = useState16(false);
7054
7373
  const [draft, setDraft] = useState16(comment.text);
@@ -7057,7 +7376,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7057
7376
  setEditing(false);
7058
7377
  if (draft !== comment.text) onUpdate({ text: draft });
7059
7378
  };
7060
- return /* @__PURE__ */ jsxs24(
7379
+ return /* @__PURE__ */ jsxs26(
7061
7380
  "div",
7062
7381
  {
7063
7382
  "data-testid": `comment-${comment.id}`,
@@ -7078,8 +7397,8 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7078
7397
  userSelect: "none"
7079
7398
  },
7080
7399
  children: [
7081
- /* @__PURE__ */ jsxs24("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7082
- !disabled && !editing && /* @__PURE__ */ jsx26(
7400
+ /* @__PURE__ */ jsxs26("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7401
+ !disabled && !editing && /* @__PURE__ */ jsx27(
7083
7402
  "button",
7084
7403
  {
7085
7404
  type: "button",
@@ -7094,7 +7413,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7094
7413
  children: "\u270F\uFE0F"
7095
7414
  }
7096
7415
  ),
7097
- !disabled && /* @__PURE__ */ jsx26(
7416
+ !disabled && /* @__PURE__ */ jsx27(
7098
7417
  "button",
7099
7418
  {
7100
7419
  type: "button",
@@ -7106,7 +7425,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7106
7425
  }
7107
7426
  )
7108
7427
  ] }),
7109
- editing ? /* @__PURE__ */ jsx26(
7428
+ editing ? /* @__PURE__ */ jsx27(
7110
7429
  "textarea",
7111
7430
  {
7112
7431
  ref: textareaRef,
@@ -7132,7 +7451,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7132
7451
  },
7133
7452
  "data-testid": `comment-textarea-${comment.id}`
7134
7453
  }
7135
- ) : /* @__PURE__ */ jsx26(
7454
+ ) : /* @__PURE__ */ jsx27(
7136
7455
  "div",
7137
7456
  {
7138
7457
  onDoubleClick: () => {
@@ -7142,7 +7461,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
7142
7461
  }
7143
7462
  },
7144
7463
  style: { whiteSpace: "pre-wrap", wordBreak: "break-word", minHeight: 20 },
7145
- children: comment.text || /* @__PURE__ */ jsx26("em", { style: { color: "#94a3b8" }, children: "empty note" })
7464
+ children: comment.text || /* @__PURE__ */ jsx27("em", { style: { color: "#94a3b8" }, children: "empty note" })
7146
7465
  }
7147
7466
  )
7148
7467
  ]
@@ -7167,7 +7486,7 @@ import {
7167
7486
  registerWorkflowSchema,
7168
7487
  revealIdInEditor
7169
7488
  } from "@cyoda/workflow-monaco";
7170
- import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
7489
+ import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
7171
7490
  function WorkflowJsonEditor({
7172
7491
  document: document2,
7173
7492
  issues,
@@ -7292,7 +7611,7 @@ function WorkflowJsonEditor({
7292
7611
  return () => window.clearTimeout(timeout);
7293
7612
  }, [document2, selectedId, visible]);
7294
7613
  if (!config) {
7295
- return /* @__PURE__ */ jsx27(
7614
+ return /* @__PURE__ */ jsx28(
7296
7615
  "div",
7297
7616
  {
7298
7617
  "data-testid": "workflow-json-unavailable",
@@ -7307,11 +7626,11 @@ function WorkflowJsonEditor({
7307
7626
  textAlign: "center",
7308
7627
  background: "#F8FAFC"
7309
7628
  },
7310
- children: /* @__PURE__ */ jsx27(UnavailableMessage, {})
7629
+ children: /* @__PURE__ */ jsx28(UnavailableMessage, {})
7311
7630
  }
7312
7631
  );
7313
7632
  }
7314
- return /* @__PURE__ */ jsxs25(
7633
+ return /* @__PURE__ */ jsxs27(
7315
7634
  "div",
7316
7635
  {
7317
7636
  "data-testid": "workflow-json-editor",
@@ -7323,8 +7642,8 @@ function WorkflowJsonEditor({
7323
7642
  minHeight: 0
7324
7643
  },
7325
7644
  children: [
7326
- /* @__PURE__ */ jsx27(JsonStatusBanner, { status }),
7327
- /* @__PURE__ */ jsx27(
7645
+ /* @__PURE__ */ jsx28(JsonStatusBanner, { status }),
7646
+ /* @__PURE__ */ jsx28(
7328
7647
  "div",
7329
7648
  {
7330
7649
  ref: containerRef,
@@ -7337,7 +7656,7 @@ function WorkflowJsonEditor({
7337
7656
  }
7338
7657
  function UnavailableMessage() {
7339
7658
  const messages = useMessages();
7340
- return /* @__PURE__ */ jsx27(Fragment10, { children: messages.editorView.unavailable });
7659
+ return /* @__PURE__ */ jsx28(Fragment11, { children: messages.editorView.unavailable });
7341
7660
  }
7342
7661
  function JsonStatusBanner({ status }) {
7343
7662
  const messages = useMessages();
@@ -7346,7 +7665,7 @@ function JsonStatusBanner({ status }) {
7346
7665
  }
7347
7666
  const tone = status.status === "semantic-errors" ? { border: "#FCD34D", bg: "#FFFBEB", text: "#92400E" } : { border: "#FCA5A5", bg: "#FEF2F2", text: "#991B1B" };
7348
7667
  const body = status.status === "semantic-errors" ? messages.editorView.semanticErrors : status.status === "invalid-schema" ? messages.editorView.invalidSchema : `${messages.editorView.invalidJson}${status.message ? ` ${status.message}` : ""}`;
7349
- return /* @__PURE__ */ jsx27(
7668
+ return /* @__PURE__ */ jsx28(
7350
7669
  "div",
7351
7670
  {
7352
7671
  role: "status",
@@ -7390,7 +7709,7 @@ function selectionFromJsonId(doc, id) {
7390
7709
  }
7391
7710
 
7392
7711
  // src/components/WorkflowEditor.tsx
7393
- import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
7712
+ import { Fragment as Fragment12, jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
7394
7713
  function hasPersistedWorkflowUi(meta) {
7395
7714
  return !!meta && Object.values(meta).some((value) => value !== void 0);
7396
7715
  }
@@ -7466,6 +7785,9 @@ function WorkflowEditor({
7466
7785
  const [helpOpen, setHelpOpen] = useState18(false);
7467
7786
  const [reconnectError, setReconnectError] = useState18(null);
7468
7787
  const [layoutKey, setLayoutKey] = useState18(0);
7788
+ const [layoutPref, setLayoutPref] = useState18(
7789
+ () => loadLayoutPref(localStorageKey, layoutOptions)
7790
+ );
7469
7791
  const [activeSurface, setActiveSurface] = useState18("graph");
7470
7792
  const [jsonStatus, setJsonStatus] = useState18({ status: "idle" });
7471
7793
  const [openIssueSeverity, setOpenIssueSeverity] = useState18(null);
@@ -7649,6 +7971,30 @@ function WorkflowEditor({
7649
7971
  );
7650
7972
  setLayoutKey((k) => k + 1);
7651
7973
  }, [state.activeWorkflow, state.document, actions]);
7974
+ useEffect13(() => {
7975
+ saveLayoutPref(localStorageKey, layoutPref);
7976
+ }, [layoutPref, localStorageKey]);
7977
+ const propLayoutRef = useRef16({
7978
+ orientation: layoutOptions?.orientation,
7979
+ preset: layoutOptions?.preset
7980
+ });
7981
+ useEffect13(() => {
7982
+ const nextO = layoutOptions?.orientation;
7983
+ const nextP = layoutOptions?.preset;
7984
+ if (nextO === propLayoutRef.current.orientation && nextP === propLayoutRef.current.preset) return;
7985
+ propLayoutRef.current = { orientation: nextO, preset: nextP };
7986
+ setLayoutPref((prev) => ({
7987
+ orientation: nextO ?? prev.orientation,
7988
+ preset: nextP ?? prev.preset
7989
+ }));
7990
+ }, [layoutOptions?.orientation, layoutOptions?.preset]);
7991
+ const applyLayoutPref = useCallback3(
7992
+ (update) => {
7993
+ setLayoutPref((prev) => ({ ...prev, ...update }));
7994
+ handleAutoLayout();
7995
+ },
7996
+ [handleAutoLayout]
7997
+ );
7652
7998
  const openAddStateModal = useCallback3((position) => {
7653
7999
  const resolved = position ?? newStatePositionRef.current?.() ?? void 0;
7654
8000
  setPendingAddState(resolved ? { position: resolved } : {});
@@ -7790,6 +8136,15 @@ function WorkflowEditor({
7790
8136
  },
7791
8137
  [actions]
7792
8138
  );
8139
+ const toggleWorkflowSettings = useCallback3(() => {
8140
+ if (inspectorOpen && selectionRef.current?.kind === "workflow") {
8141
+ handleSelectionChange(null);
8142
+ } else {
8143
+ handleSelectionChange(
8144
+ activeWorkflowRef.current ? { kind: "workflow", workflow: activeWorkflowRef.current } : null
8145
+ );
8146
+ }
8147
+ }, [inspectorOpen, handleSelectionChange]);
7793
8148
  const confirmAddState = useCallback3(
7794
8149
  (name) => {
7795
8150
  const workflow = state.activeWorkflow;
@@ -7929,10 +8284,15 @@ function WorkflowEditor({
7929
8284
  if (!wf) return null;
7930
8285
  return wf.states[pendingConnect.fromState] ?? null;
7931
8286
  }, [pendingConnect, state.document]);
7932
- const orientation = layoutOptions?.orientation ?? "vertical";
8287
+ const orientation = layoutPref.orientation;
7933
8288
  const effectiveLayoutOptions = useMemo7(
7934
- () => ({ ...layoutOptions, pinned: pinnedNodes }),
7935
- [layoutOptions, pinnedNodes]
8289
+ () => ({
8290
+ ...layoutOptions,
8291
+ orientation: layoutPref.orientation,
8292
+ preset: layoutPref.preset,
8293
+ pinned: pinnedNodes
8294
+ }),
8295
+ [layoutOptions, layoutPref, pinnedNodes]
7936
8296
  );
7937
8297
  const savedViewport = state.activeWorkflow ? state.document.meta.workflowUi[state.activeWorkflow]?.viewports?.[orientation] : void 0;
7938
8298
  useEffect13(() => {
@@ -7974,13 +8334,13 @@ function WorkflowEditor({
7974
8334
  if (readOnly || anyModalOpen) return;
7975
8335
  openAddStateModal({ x, y });
7976
8336
  }, [anyModalOpen, openAddStateModal, readOnly]);
7977
- const graphPane = /* @__PURE__ */ jsxs26(
8337
+ const graphPane = /* @__PURE__ */ jsxs28(
7978
8338
  "div",
7979
8339
  {
7980
8340
  "data-testid": "workflow-editor-graph-pane",
7981
8341
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%", position: "relative" },
7982
8342
  children: [
7983
- /* @__PURE__ */ jsx28(
8343
+ /* @__PURE__ */ jsx29(
7984
8344
  Canvas,
7985
8345
  {
7986
8346
  graph: derived.graph,
@@ -7993,6 +8353,7 @@ function WorkflowEditor({
7993
8353
  transitionPositions,
7994
8354
  onTransitionLabelDragEnd: handleTransitionLabelDragEnd,
7995
8355
  onSelectionChange: handleSelectionChange,
8356
+ onToggleWorkflowSettings: toggleWorkflowSettings,
7996
8357
  onViewportChange: handleViewportChange,
7997
8358
  onConnect: handleConnect,
7998
8359
  onReconnect: handleReconnect,
@@ -8018,6 +8379,8 @@ function WorkflowEditor({
8018
8379
  onUndo: !readOnly ? actions.undo : void 0,
8019
8380
  onRedo: !readOnly ? actions.redo : void 0,
8020
8381
  onAutoLayout: !readOnly ? handleAutoLayout : void 0,
8382
+ onSetLayoutOrientation: !readOnly ? (o) => applyLayoutPref({ orientation: o }) : void 0,
8383
+ onSetLayoutDensity: !readOnly ? (p) => applyLayoutPref({ preset: p }) : void 0,
8021
8384
  isFullscreen,
8022
8385
  onToggleFullscreen: handleToggleFullscreen,
8023
8386
  resizeKey: inspectorVisible ? 1 : 0,
@@ -8025,7 +8388,7 @@ function WorkflowEditor({
8025
8388
  helpLabel: mergedMessages.toolbar.help
8026
8389
  }
8027
8390
  ),
8028
- reconnectError && /* @__PURE__ */ jsx28(
8391
+ reconnectError && /* @__PURE__ */ jsx29(
8029
8392
  "div",
8030
8393
  {
8031
8394
  role: "alert",
@@ -8050,7 +8413,7 @@ function WorkflowEditor({
8050
8413
  state.activeWorkflow && (() => {
8051
8414
  const comments = state.document.meta.workflowUi[state.activeWorkflow]?.comments;
8052
8415
  if (!comments) return null;
8053
- return Object.values(comments).map((c) => /* @__PURE__ */ jsx28(
8416
+ return Object.values(comments).map((c) => /* @__PURE__ */ jsx29(
8054
8417
  CommentNode,
8055
8418
  {
8056
8419
  comment: c,
@@ -8073,12 +8436,12 @@ function WorkflowEditor({
8073
8436
  ]
8074
8437
  }
8075
8438
  );
8076
- const jsonPane = enableJsonEditor ? /* @__PURE__ */ jsx28(
8439
+ const jsonPane = enableJsonEditor ? /* @__PURE__ */ jsx29(
8077
8440
  "div",
8078
8441
  {
8079
8442
  "data-testid": "workflow-editor-json-pane",
8080
8443
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%" },
8081
- children: /* @__PURE__ */ jsx28(
8444
+ children: /* @__PURE__ */ jsx29(
8082
8445
  WorkflowJsonEditor,
8083
8446
  {
8084
8447
  document: state.document,
@@ -8094,7 +8457,7 @@ function WorkflowEditor({
8094
8457
  )
8095
8458
  }
8096
8459
  ) : null;
8097
- return /* @__PURE__ */ jsx28(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ jsx28(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ jsx28(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ jsxs26(
8460
+ return /* @__PURE__ */ jsx29(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ jsx29(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ jsx29(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ jsxs28(
8098
8461
  "div",
8099
8462
  {
8100
8463
  ref: editorContainerRef,
@@ -8115,7 +8478,7 @@ function WorkflowEditor({
8115
8478
  onKeyDown: handleKeyDown,
8116
8479
  tabIndex: -1,
8117
8480
  children: [
8118
- chrome?.tabs !== false && showTabs && /* @__PURE__ */ jsx28(
8481
+ chrome?.tabs !== false && showTabs && /* @__PURE__ */ jsx29(
8119
8482
  WorkflowTabs,
8120
8483
  {
8121
8484
  workflows,
@@ -8142,9 +8505,9 @@ function WorkflowEditor({
8142
8505
  onVersionChange: handleVersionChange
8143
8506
  }
8144
8507
  ),
8145
- /* @__PURE__ */ jsxs26("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
8146
- /* @__PURE__ */ jsxs26("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
8147
- (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ jsxs26(
8508
+ /* @__PURE__ */ jsxs28("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
8509
+ /* @__PURE__ */ jsxs28("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
8510
+ (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ jsxs28(
8148
8511
  "div",
8149
8512
  {
8150
8513
  style: {
@@ -8158,8 +8521,8 @@ function WorkflowEditor({
8158
8521
  },
8159
8522
  "data-testid": "workflow-editor-surface-tabs",
8160
8523
  children: [
8161
- enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ jsxs26(Fragment11, { children: [
8162
- /* @__PURE__ */ jsx28(
8524
+ enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ jsxs28(Fragment12, { children: [
8525
+ /* @__PURE__ */ jsx29(
8163
8526
  SurfaceTab,
8164
8527
  {
8165
8528
  active: activeSurface === "graph",
@@ -8167,7 +8530,7 @@ function WorkflowEditor({
8167
8530
  children: mergedMessages.editorView.graph
8168
8531
  }
8169
8532
  ),
8170
- /* @__PURE__ */ jsx28(
8533
+ /* @__PURE__ */ jsx29(
8171
8534
  SurfaceTab,
8172
8535
  {
8173
8536
  active: activeSurface === "json",
@@ -8176,8 +8539,8 @@ function WorkflowEditor({
8176
8539
  }
8177
8540
  )
8178
8541
  ] }),
8179
- /* @__PURE__ */ jsx28("div", { style: { flex: 1 } }),
8180
- !readOnly && activeSurface === "graph" && /* @__PURE__ */ jsxs26(
8542
+ /* @__PURE__ */ jsx29("div", { style: { flex: 1 } }),
8543
+ !readOnly && activeSurface === "graph" && /* @__PURE__ */ jsxs28(
8181
8544
  "button",
8182
8545
  {
8183
8546
  type: "button",
@@ -8198,7 +8561,7 @@ function WorkflowEditor({
8198
8561
  cursor: "pointer"
8199
8562
  },
8200
8563
  children: [
8201
- /* @__PURE__ */ jsx28("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ jsx28("path", { d: "M12 5v14M5 12h14" }) }),
8564
+ /* @__PURE__ */ jsx29("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ jsx29("path", { d: "M12 5v14M5 12h14" }) }),
8202
8565
  mergedMessages.toolbar.addStateButton
8203
8566
  ]
8204
8567
  }
@@ -8206,7 +8569,7 @@ function WorkflowEditor({
8206
8569
  ]
8207
8570
  }
8208
8571
  ),
8209
- enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ jsxs26(
8572
+ enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ jsxs28(
8210
8573
  "div",
8211
8574
  {
8212
8575
  style: {
@@ -8219,10 +8582,10 @@ function WorkflowEditor({
8219
8582
  "data-testid": "workflow-editor-split-view",
8220
8583
  children: [
8221
8584
  graphPane,
8222
- /* @__PURE__ */ jsx28("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8585
+ /* @__PURE__ */ jsx29("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8223
8586
  ]
8224
8587
  }
8225
- ) : /* @__PURE__ */ jsxs26(
8588
+ ) : /* @__PURE__ */ jsxs28(
8226
8589
  "div",
8227
8590
  {
8228
8591
  style: {
@@ -8234,8 +8597,8 @@ function WorkflowEditor({
8234
8597
  flexDirection: "column"
8235
8598
  },
8236
8599
  children: [
8237
- graphVisible ? /* @__PURE__ */ jsx28("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8238
- enableJsonEditor ? /* @__PURE__ */ jsx28(
8600
+ graphVisible ? /* @__PURE__ */ jsx29("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8601
+ enableJsonEditor ? /* @__PURE__ */ jsx29(
8239
8602
  "div",
8240
8603
  {
8241
8604
  style: {
@@ -8252,7 +8615,7 @@ function WorkflowEditor({
8252
8615
  }
8253
8616
  )
8254
8617
  ] }),
8255
- inspectorVisible && /* @__PURE__ */ jsx28(
8618
+ inspectorVisible && /* @__PURE__ */ jsx29(
8256
8619
  InspectorFrame,
8257
8620
  {
8258
8621
  mode: placement.mode,
@@ -8262,7 +8625,7 @@ function WorkflowEditor({
8262
8625
  onDockedWidthChange: setInspectorWidth,
8263
8626
  onRestore: restoreInspector,
8264
8627
  onClose: () => handleSelectionChange(null),
8265
- children: /* @__PURE__ */ jsx28(
8628
+ children: /* @__PURE__ */ jsx29(
8266
8629
  Inspector,
8267
8630
  {
8268
8631
  document: state.document,
@@ -8281,7 +8644,7 @@ function WorkflowEditor({
8281
8644
  }
8282
8645
  )
8283
8646
  ] }),
8284
- pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ jsx28(
8647
+ pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ jsx29(
8285
8648
  AddStateModal,
8286
8649
  {
8287
8650
  existingNames: Object.keys(
@@ -8293,7 +8656,7 @@ function WorkflowEditor({
8293
8656
  onCancel: () => setPendingAddState(null)
8294
8657
  }
8295
8658
  ),
8296
- pendingDelete && /* @__PURE__ */ jsx28(
8659
+ pendingDelete && /* @__PURE__ */ jsx29(
8297
8660
  DeleteStateModal,
8298
8661
  {
8299
8662
  document: state.document,
@@ -8303,7 +8666,7 @@ function WorkflowEditor({
8303
8666
  onCancel: () => setPendingDelete(null)
8304
8667
  }
8305
8668
  ),
8306
- pendingConnect && pendingConnectState && /* @__PURE__ */ jsx28(
8669
+ pendingConnect && pendingConnectState && /* @__PURE__ */ jsx29(
8307
8670
  DragConnectModal,
8308
8671
  {
8309
8672
  source: pendingConnectState,
@@ -8313,8 +8676,8 @@ function WorkflowEditor({
8313
8676
  onCancel: () => setPendingConnect(null)
8314
8677
  }
8315
8678
  ),
8316
- helpOpen && /* @__PURE__ */ jsx28(HelpModal, { onCancel: () => setHelpOpen(false) }),
8317
- pendingVersionSwitch && /* @__PURE__ */ jsx28(
8679
+ helpOpen && /* @__PURE__ */ jsx29(HelpModal, { onCancel: () => setHelpOpen(false) }),
8680
+ pendingVersionSwitch && /* @__PURE__ */ jsx29(
8318
8681
  VersionSwitchModal,
8319
8682
  {
8320
8683
  fromVersion: `v${state.document.meta.cyodaVersion ?? LATEST_CYODA_VERSION}`,
@@ -8327,8 +8690,8 @@ function WorkflowEditor({
8327
8690
  onCancel: () => setPendingVersionSwitch(null)
8328
8691
  }
8329
8692
  ),
8330
- chrome?.toolbar !== false && /* @__PURE__ */ jsxs26("div", { style: { position: "relative" }, children: [
8331
- /* @__PURE__ */ jsx28(
8693
+ chrome?.toolbar !== false && /* @__PURE__ */ jsxs28("div", { style: { position: "relative" }, children: [
8694
+ /* @__PURE__ */ jsx29(
8332
8695
  Toolbar,
8333
8696
  {
8334
8697
  derived,
@@ -8343,7 +8706,7 @@ function WorkflowEditor({
8343
8706
  toolbarEnd
8344
8707
  }
8345
8708
  ),
8346
- /* @__PURE__ */ jsx28(
8709
+ /* @__PURE__ */ jsx29(
8347
8710
  IssuesDrawer,
8348
8711
  {
8349
8712
  open: openIssueSeverity !== null,
@@ -8415,7 +8778,10 @@ function buildReconnectTransaction(doc, edge, connection) {
8415
8778
  summary: `Reconnect transition "${transition.name}"`,
8416
8779
  patches: patches2,
8417
8780
  inverses: inverses2,
8418
- selectionAfter: { kind: "transition", transitionUuid: edge.id }
8781
+ // A pure re-anchor is a layout tweak — preserve the current selection
8782
+ // (omitting selectionAfter). Changing the target state is a structural
8783
+ // edit, so select the transition.
8784
+ ...targetChanged ? { selectionAfter: { kind: "transition", transitionUuid: edge.id } } : {}
8419
8785
  }
8420
8786
  };
8421
8787
  }
@@ -8523,7 +8889,7 @@ function SurfaceTab({
8523
8889
  onClick,
8524
8890
  children
8525
8891
  }) {
8526
- return /* @__PURE__ */ jsx28(
8892
+ return /* @__PURE__ */ jsx29(
8527
8893
  "button",
8528
8894
  {
8529
8895
  type: "button",
@@ -8656,7 +9022,7 @@ function useSaveFlow(args) {
8656
9022
 
8657
9023
  // src/save/SaveConfirmModal.tsx
8658
9024
  import { useState as useState20 } from "react";
8659
- import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
9025
+ import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
8660
9026
  function SaveConfirmModal({
8661
9027
  mode,
8662
9028
  requiresExplicitConfirm,
@@ -8669,14 +9035,14 @@ function SaveConfirmModal({
8669
9035
  const [ackMode, setAckMode] = useState20(!requiresExplicitConfirm);
8670
9036
  const [ackWarnings, setAckWarnings] = useState20(warningCount === 0);
8671
9037
  const blocked = !ackMode || !ackWarnings;
8672
- return /* @__PURE__ */ jsxs27(ModalFrame, { onCancel, children: [
8673
- /* @__PURE__ */ jsx29("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
8674
- /* @__PURE__ */ jsxs27("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
9038
+ return /* @__PURE__ */ jsxs29(ModalFrame, { onCancel, children: [
9039
+ /* @__PURE__ */ jsx30("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
9040
+ /* @__PURE__ */ jsxs29("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
8675
9041
  messages.saveConfirm.modeLabel,
8676
9042
  ": ",
8677
- /* @__PURE__ */ jsx29("strong", { children: mode })
9043
+ /* @__PURE__ */ jsx30("strong", { children: mode })
8678
9044
  ] }),
8679
- diffSummary2 && /* @__PURE__ */ jsx29(
9045
+ diffSummary2 && /* @__PURE__ */ jsx30(
8680
9046
  "pre",
8681
9047
  {
8682
9048
  style: {
@@ -8695,8 +9061,8 @@ function SaveConfirmModal({
8695
9061
  children: diffSummary2
8696
9062
  }
8697
9063
  ),
8698
- requiresExplicitConfirm && /* @__PURE__ */ jsxs27("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8699
- /* @__PURE__ */ jsx29(
9064
+ requiresExplicitConfirm && /* @__PURE__ */ jsxs29("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
9065
+ /* @__PURE__ */ jsx30(
8700
9066
  "input",
8701
9067
  {
8702
9068
  type: "checkbox",
@@ -8704,10 +9070,10 @@ function SaveConfirmModal({
8704
9070
  onChange: (e) => setAckMode(e.target.checked)
8705
9071
  }
8706
9072
  ),
8707
- /* @__PURE__ */ jsx29("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
9073
+ /* @__PURE__ */ jsx30("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8708
9074
  ] }),
8709
- warningCount > 0 && /* @__PURE__ */ jsxs27("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8710
- /* @__PURE__ */ jsx29(
9075
+ warningCount > 0 && /* @__PURE__ */ jsxs29("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
9076
+ /* @__PURE__ */ jsx30(
8711
9077
  "input",
8712
9078
  {
8713
9079
  type: "checkbox",
@@ -8715,11 +9081,11 @@ function SaveConfirmModal({
8715
9081
  onChange: (e) => setAckWarnings(e.target.checked)
8716
9082
  }
8717
9083
  ),
8718
- /* @__PURE__ */ jsx29("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
9084
+ /* @__PURE__ */ jsx30("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8719
9085
  ] }),
8720
- /* @__PURE__ */ jsxs27("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
8721
- /* @__PURE__ */ jsx29("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
8722
- /* @__PURE__ */ jsx29(
9086
+ /* @__PURE__ */ jsxs29("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
9087
+ /* @__PURE__ */ jsx30("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
9088
+ /* @__PURE__ */ jsx30(
8723
9089
  "button",
8724
9090
  {
8725
9091
  type: "button",
@@ -8757,10 +9123,10 @@ var primaryBtn5 = {
8757
9123
  };
8758
9124
 
8759
9125
  // src/save/ConflictBanner.tsx
8760
- import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
9126
+ import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
8761
9127
  function ConflictBanner({ onReload, onForceOverwrite }) {
8762
9128
  const messages = useMessages();
8763
- return /* @__PURE__ */ jsxs28(
9129
+ return /* @__PURE__ */ jsxs30(
8764
9130
  "div",
8765
9131
  {
8766
9132
  style: {
@@ -8776,8 +9142,8 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8776
9142
  role: "alert",
8777
9143
  "data-testid": "conflict-banner",
8778
9144
  children: [
8779
- /* @__PURE__ */ jsx30("span", { style: { flex: 1 }, children: messages.conflict.message }),
8780
- /* @__PURE__ */ jsx30(
9145
+ /* @__PURE__ */ jsx31("span", { style: { flex: 1 }, children: messages.conflict.message }),
9146
+ /* @__PURE__ */ jsx31(
8781
9147
  "button",
8782
9148
  {
8783
9149
  type: "button",
@@ -8787,7 +9153,7 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8787
9153
  children: messages.conflict.reload
8788
9154
  }
8789
9155
  ),
8790
- /* @__PURE__ */ jsx30(
9156
+ /* @__PURE__ */ jsx31(
8791
9157
  "button",
8792
9158
  {
8793
9159
  type: "button",