@cyoda/workflow-react 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/WorkflowEditor.tsx
2
- import { useCallback as useCallback3, useEffect as useEffect11, useMemo as useMemo7, useRef as useRef14, useState as useState17 } from "react";
2
+ import { useCallback as useCallback3, useEffect as useEffect13, useMemo as useMemo7, useRef as useRef16, useState as useState18 } from "react";
3
3
  import {
4
4
  applyPatch as applyPatch2,
5
5
  invertPatch as invertPatch2,
@@ -96,6 +96,13 @@ var defaultMessages = {
96
96
  processes: "Processes",
97
97
  criterion: "Criterion",
98
98
  criteria: "Criteria",
99
+ annotations: "Annotations",
100
+ annotationsAdd: "Add annotations",
101
+ annotationsApply: "Apply",
102
+ annotationsRevert: "Revert",
103
+ annotationsRemove: "Remove",
104
+ annotationsDocChanged: "Document changed underneath \u2014 Revert to reload.",
105
+ format: "Format",
99
106
  executionMode: "Execution mode",
100
107
  addProcessor: "Add processor",
101
108
  removeProcessor: "Remove",
@@ -117,7 +124,12 @@ var defaultMessages = {
117
124
  anchorBottomRight: "Bottom right",
118
125
  anchorLeftTop: "Left top",
119
126
  anchorLeft: "Left",
120
- anchorLeftBottom: "Left bottom"
127
+ anchorLeftBottom: "Left bottom",
128
+ detachPanel: "Detach panel",
129
+ dockPanel: "Dock panel",
130
+ minimize: "Minimize",
131
+ restore: "Restore",
132
+ minimizedTitle: "Inspector"
121
133
  },
122
134
  confirmDelete: {
123
135
  title: "Delete state?",
@@ -171,7 +183,9 @@ var defaultMessages = {
171
183
  noneAutomated: "No criterion. This automated transition will fire as soon as the entity reaches this state.",
172
184
  noneAutomatedWarning: "Automated transitions without criteria should usually be last in the transition order.",
173
185
  cancel: "Cancel",
174
- applyModal: "Apply"
186
+ applyModal: "Apply",
187
+ revert: "Revert",
188
+ collapse: "Collapse"
175
189
  }
176
190
  };
177
191
 
@@ -243,6 +257,8 @@ function summarize(patch) {
243
257
  return `Reorder processor`;
244
258
  case "setCriterion":
245
259
  return patch.criterion ? `Set criterion` : `Clear criterion`;
260
+ case "setAnnotations":
261
+ return patch.annotations ? `Set annotations` : `Clear annotations`;
246
262
  case "setImportMode":
247
263
  return `Set import mode to "${patch.mode}"`;
248
264
  case "setEntity":
@@ -2726,7 +2742,17 @@ function CanvasInner({
2726
2742
  onHelp && /* @__PURE__ */ jsxs4(Fragment3, { children: [
2727
2743
  /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } }),
2728
2744
  /* @__PURE__ */ jsx5(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ jsx5(HelpIcon, {}) })
2729
- ] })
2745
+ ] }),
2746
+ /* @__PURE__ */ jsx5("div", { style: { height: 1, background: "#E2E8F0" } }),
2747
+ /* @__PURE__ */ jsx5(
2748
+ CtrlBtn,
2749
+ {
2750
+ onClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2751
+ title: "Workflow settings",
2752
+ testId: "canvas-workflow-settings",
2753
+ children: /* @__PURE__ */ jsx5(WorkflowSettingsIcon, {})
2754
+ }
2755
+ )
2730
2756
  ]
2731
2757
  }
2732
2758
  ),
@@ -2846,6 +2872,16 @@ function HelpIcon() {
2846
2872
  /* @__PURE__ */ jsx5("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
2847
2873
  ] });
2848
2874
  }
2875
+ 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" })
2883
+ ] });
2884
+ }
2849
2885
  function Canvas(props) {
2850
2886
  return /* @__PURE__ */ jsx5(ReactFlowProvider, { children: /* @__PURE__ */ jsx5(CanvasInner, { ...props }) });
2851
2887
  }
@@ -2866,7 +2902,7 @@ function resolveConnection(doc, connection) {
2866
2902
  }
2867
2903
 
2868
2904
  // src/inspector/Inspector.tsx
2869
- import { useMemo as useMemo4, useState as useState10 } from "react";
2905
+ import { useMemo as useMemo4, useState as useState11 } from "react";
2870
2906
  import { serializeEditorDocument } from "@cyoda/workflow-core";
2871
2907
 
2872
2908
  // src/style/tokens.ts
@@ -3331,16 +3367,301 @@ var smallSelectStyle = {
3331
3367
  userSelect: "none"
3332
3368
  };
3333
3369
 
3334
- // src/inspector/WorkflowForm.tsx
3370
+ // src/inspector/AnnotationsField.tsx
3371
+ import { useEffect as useEffect4, useRef as useRef6, useState as useState6 } from "react";
3372
+
3373
+ // src/inspector/JsonMonacoField.tsx
3374
+ import { useEffect as useEffect3, useRef as useRef5 } from "react";
3375
+
3376
+ // src/inspector/CriterionMonacoContext.tsx
3377
+ import { createContext as createContext3, useContext as useContext4 } from "react";
3378
+ var CriterionMonacoContext = createContext3(null);
3379
+ var CriterionMonacoProvider = CriterionMonacoContext.Provider;
3380
+ function useCriterionMonaco() {
3381
+ return useContext4(CriterionMonacoContext);
3382
+ }
3383
+
3384
+ // src/components/monacoDisposal.ts
3385
+ var installed = false;
3386
+ function isMonacoCanceled(reason) {
3387
+ if (reason == null || typeof reason !== "object") return false;
3388
+ return reason.name === "Canceled";
3389
+ }
3390
+ function installMonacoCancellationFilter() {
3391
+ if (installed || typeof window === "undefined") return;
3392
+ installed = true;
3393
+ window.addEventListener("unhandledrejection", (e) => {
3394
+ if (isMonacoCanceled(e.reason)) e.preventDefault();
3395
+ });
3396
+ }
3397
+ installMonacoCancellationFilter();
3398
+
3399
+ // src/inspector/JsonMonacoField.tsx
3335
3400
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3401
+ function reformat(text) {
3402
+ try {
3403
+ return JSON.stringify(JSON.parse(text), null, 2);
3404
+ } catch {
3405
+ return null;
3406
+ }
3407
+ }
3408
+ function JsonMonacoField(props) {
3409
+ const monaco = useCriterionMonaco();
3410
+ const messages = useMessages();
3411
+ const onFormat = () => {
3412
+ const next = reformat(props.buffer);
3413
+ if (next !== null && next !== props.buffer) props.onChange(next);
3414
+ };
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(
3417
+ "button",
3418
+ {
3419
+ type: "button",
3420
+ onClick: onFormat,
3421
+ disabled: props.disabled,
3422
+ "data-testid": `${props.testId}-format`,
3423
+ style: { ...ghostBtnStyle, fontSize: 11, padding: "2px 8px" },
3424
+ children: messages.inspector.format
3425
+ }
3426
+ ) }),
3427
+ monaco ? /* @__PURE__ */ jsx7(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ jsx7(
3428
+ "textarea",
3429
+ {
3430
+ value: props.buffer,
3431
+ disabled: props.disabled,
3432
+ rows: 12,
3433
+ "data-testid": props.testId,
3434
+ onChange: (e) => props.onChange(e.target.value),
3435
+ style: {
3436
+ fontFamily: fonts.mono,
3437
+ fontSize: 12,
3438
+ padding: 8,
3439
+ whiteSpace: "pre-wrap",
3440
+ wordBreak: "break-word",
3441
+ border: `1px solid ${colors.border}`,
3442
+ borderRadius: radii.sm,
3443
+ background: colors.surface,
3444
+ resize: "vertical",
3445
+ minHeight: props.minHeightPx ?? 120
3446
+ }
3447
+ }
3448
+ )
3449
+ ] });
3450
+ }
3451
+ function MonacoPane({
3452
+ monaco,
3453
+ buffer,
3454
+ disabled,
3455
+ modelUri,
3456
+ onChange,
3457
+ seed,
3458
+ registerSchema,
3459
+ minHeightPx = 120,
3460
+ maxHeightPx = 480,
3461
+ testId
3462
+ }) {
3463
+ const containerRef = useRef5(null);
3464
+ const editorRef = useRef5(null);
3465
+ const modelRef = useRef5(null);
3466
+ useEffect3(() => {
3467
+ if (!containerRef.current || editorRef.current) return;
3468
+ const model = monaco.editor.createModel(buffer, "json", monaco.Uri.parse(modelUri));
3469
+ modelRef.current = model;
3470
+ const editor = monaco.editor.create(containerRef.current, {
3471
+ model,
3472
+ automaticLayout: true,
3473
+ minimap: { enabled: false },
3474
+ wordWrap: "on",
3475
+ fontSize: 13,
3476
+ tabSize: 2,
3477
+ scrollBeyondLastLine: false,
3478
+ theme: "vs",
3479
+ readOnly: disabled
3480
+ });
3481
+ editorRef.current = editor;
3482
+ installMonacoCancellationFilter();
3483
+ const schemaHandle = registerSchema?.(monaco) ?? null;
3484
+ const applyHeight = () => {
3485
+ const h = Math.min(Math.max(editor.getContentHeight?.() ?? minHeightPx, minHeightPx), maxHeightPx);
3486
+ if (containerRef.current) containerRef.current.style.height = `${h}px`;
3487
+ editor.layout?.();
3488
+ };
3489
+ applyHeight();
3490
+ const sizeSub = editor.onDidContentSizeChange?.(applyHeight) ?? { dispose() {
3491
+ } };
3492
+ const sub = model.onDidChangeContent(() => onChange(model.getValue()));
3493
+ return () => {
3494
+ sub.dispose();
3495
+ sizeSub.dispose();
3496
+ schemaHandle?.dispose();
3497
+ editor.dispose();
3498
+ editorRef.current = null;
3499
+ model.dispose();
3500
+ modelRef.current = null;
3501
+ };
3502
+ }, [monaco, modelUri]);
3503
+ useEffect3(() => {
3504
+ const model = modelRef.current;
3505
+ if (model && seed !== void 0 && model.getValue() !== seed) model.setValue(seed);
3506
+ }, [seed]);
3507
+ useEffect3(() => {
3508
+ editorRef.current?.updateOptions?.({ readOnly: disabled });
3509
+ }, [disabled]);
3510
+ return /* @__PURE__ */ jsx7(
3511
+ "div",
3512
+ {
3513
+ ref: containerRef,
3514
+ "data-testid": testId,
3515
+ style: { height: minHeightPx, border: `1px solid ${colors.border}`, borderRadius: radii.sm }
3516
+ }
3517
+ );
3518
+ }
3519
+
3520
+ // src/inspector/annotationsJson.ts
3521
+ import { ANNOTATIONS_MAX_BYTES } from "@cyoda/workflow-core";
3522
+ function annotationsModelUri(key) {
3523
+ return `cyoda://annotations/${key}.json`;
3524
+ }
3525
+ function annotationBytes(value) {
3526
+ return new TextEncoder().encode(JSON.stringify(value)).length;
3527
+ }
3528
+ function sameJson(a, b) {
3529
+ return JSON.stringify(a) === JSON.stringify(b);
3530
+ }
3531
+ function parseAnnotationsJson(text) {
3532
+ let raw;
3533
+ try {
3534
+ raw = JSON.parse(text);
3535
+ } catch {
3536
+ return { annotations: null, error: "Invalid JSON." };
3537
+ }
3538
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
3539
+ return { annotations: null, error: "Annotations must be a JSON object." };
3540
+ }
3541
+ const bytes = annotationBytes(raw);
3542
+ if (bytes > ANNOTATIONS_MAX_BYTES) {
3543
+ return {
3544
+ annotations: null,
3545
+ error: `Annotations are ${bytes} bytes, over the ${ANNOTATIONS_MAX_BYTES}-byte limit.`
3546
+ };
3547
+ }
3548
+ return { annotations: raw, error: null };
3549
+ }
3550
+
3551
+ // src/inspector/AnnotationsField.tsx
3552
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3553
+ var pretty = (v) => JSON.stringify(v, null, 2);
3554
+ function AnnotationsField(props) {
3555
+ const messages = useMessages();
3556
+ 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(
3560
+ "button",
3561
+ {
3562
+ type: "button",
3563
+ style: primaryBtn,
3564
+ "data-testid": "inspector-annotations-add",
3565
+ onClick: () => props.onCommit({}),
3566
+ children: messages.inspector.annotationsAdd
3567
+ }
3568
+ )
3569
+ ] });
3570
+ }
3571
+ return /* @__PURE__ */ jsx8(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3572
+ }
3573
+ function AnnotationsEditor({
3574
+ value,
3575
+ disabled,
3576
+ modelKey,
3577
+ onCommit,
3578
+ onRemove,
3579
+ showLabel
3580
+ }) {
3581
+ const messages = useMessages();
3582
+ const [buffer, setBuffer] = useState6(() => pretty(value));
3583
+ const [docChanged, setDocChanged] = useState6(false);
3584
+ const prevValueRef = useRef6(value);
3585
+ useEffect4(() => {
3586
+ if (sameJson(prevValueRef.current, value)) return;
3587
+ const parsed = parseAnnotationsJson(buffer).annotations;
3588
+ if (parsed !== null && sameJson(parsed, value)) {
3589
+ setDocChanged(false);
3590
+ } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3591
+ setBuffer(pretty(value));
3592
+ setDocChanged(false);
3593
+ } else {
3594
+ setDocChanged(true);
3595
+ }
3596
+ prevValueRef.current = value;
3597
+ }, [value, buffer]);
3598
+ const result = parseAnnotationsJson(buffer);
3599
+ const dirty = result.annotations !== null && !sameJson(result.annotations, value);
3600
+ const applyEnabled = !disabled && result.annotations !== null && dirty;
3601
+ const canRevert = buffer !== pretty(value);
3602
+ const apply = () => {
3603
+ if (!applyEnabled || result.annotations === null) return;
3604
+ onCommit(result.annotations);
3605
+ setDocChanged(false);
3606
+ };
3607
+ const revert = () => {
3608
+ setBuffer(pretty(value));
3609
+ setDocChanged(false);
3610
+ };
3611
+ return /* @__PURE__ */ jsxs7("div", { style: sectionStyle, children: [
3612
+ showLabel !== false && /* @__PURE__ */ jsx8(SectionLabel, {}),
3613
+ /* @__PURE__ */ jsx8(
3614
+ JsonMonacoField,
3615
+ {
3616
+ buffer,
3617
+ disabled,
3618
+ modelUri: annotationsModelUri(modelKey),
3619
+ onChange: setBuffer,
3620
+ seed: buffer,
3621
+ testId: "annotations-json-editor"
3622
+ }
3623
+ ),
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(
3628
+ "button",
3629
+ {
3630
+ type: "button",
3631
+ onClick: apply,
3632
+ disabled: !applyEnabled,
3633
+ style: applyEnabled ? primaryBtn : disabledBtn,
3634
+ "data-testid": "inspector-annotations-apply",
3635
+ children: messages.inspector.annotationsApply
3636
+ }
3637
+ ),
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 })
3640
+ ] })
3641
+ ] });
3642
+ }
3643
+ function SectionLabel() {
3644
+ 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 });
3646
+ }
3647
+ var sectionStyle = { display: "flex", flexDirection: "column", gap: 8 };
3648
+ var ghostBtn = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
3649
+ var primaryBtn = { ...ghostBtn, background: colors.primary, color: "white", borderColor: colors.primary };
3650
+ var disabledBtn = { ...primaryBtn, opacity: 0.5, cursor: "not-allowed" };
3651
+ var dangerBtn = { ...ghostBtn, background: colors.dangerBg, borderColor: colors.dangerBorder, color: colors.danger };
3652
+ var errorStyle = { color: colors.danger, fontSize: 11 };
3653
+ var warnStyle = { color: colors.warning, fontSize: 11 };
3654
+
3655
+ // src/inspector/WorkflowForm.tsx
3656
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3336
3657
  function WorkflowForm({
3337
3658
  workflow,
3338
3659
  disabled,
3339
3660
  onDispatch
3340
3661
  }) {
3341
3662
  const messages = useMessages();
3342
- return /* @__PURE__ */ jsxs6(FieldGroup, { title: messages.inspector.properties, children: [
3343
- /* @__PURE__ */ jsx7(
3663
+ return /* @__PURE__ */ jsxs8(FieldGroup, { title: messages.inspector.properties, children: [
3664
+ /* @__PURE__ */ jsx9(
3344
3665
  TextField,
3345
3666
  {
3346
3667
  label: messages.inspector.name,
@@ -3350,7 +3671,7 @@ function WorkflowForm({
3350
3671
  testId: "inspector-workflow-name"
3351
3672
  }
3352
3673
  ),
3353
- /* @__PURE__ */ jsx7(
3674
+ /* @__PURE__ */ jsx9(
3354
3675
  TextField,
3355
3676
  {
3356
3677
  label: messages.inspector.version,
@@ -3365,7 +3686,7 @@ function WorkflowForm({
3365
3686
  testId: "inspector-workflow-version"
3366
3687
  }
3367
3688
  ),
3368
- /* @__PURE__ */ jsx7(
3689
+ /* @__PURE__ */ jsx9(
3369
3690
  TextField,
3370
3691
  {
3371
3692
  label: messages.inspector.description,
@@ -3381,7 +3702,7 @@ function WorkflowForm({
3381
3702
  testId: "inspector-workflow-desc"
3382
3703
  }
3383
3704
  ),
3384
- /* @__PURE__ */ jsx7(
3705
+ /* @__PURE__ */ jsx9(
3385
3706
  CheckboxField,
3386
3707
  {
3387
3708
  label: messages.inspector.active,
@@ -3395,7 +3716,7 @@ function WorkflowForm({
3395
3716
  testId: "inspector-workflow-active"
3396
3717
  }
3397
3718
  ),
3398
- /* @__PURE__ */ jsx7(
3719
+ /* @__PURE__ */ jsx9(
3399
3720
  TextField,
3400
3721
  {
3401
3722
  label: messages.inspector.initialState,
@@ -3409,14 +3730,24 @@ function WorkflowForm({
3409
3730
  }),
3410
3731
  testId: "inspector-workflow-initial"
3411
3732
  }
3733
+ ),
3734
+ /* @__PURE__ */ jsx9(
3735
+ AnnotationsField,
3736
+ {
3737
+ value: workflow.annotations,
3738
+ disabled,
3739
+ modelKey: `workflow-${workflow.name}`,
3740
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name }, annotations }),
3741
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name } })
3742
+ }
3412
3743
  )
3413
3744
  ] });
3414
3745
  }
3415
3746
 
3416
3747
  // src/inspector/StateForm.tsx
3417
- import { useState as useState6 } from "react";
3748
+ import { useState as useState7 } from "react";
3418
3749
  import { NAME_REGEX } from "@cyoda/workflow-core";
3419
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3750
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3420
3751
  function StateForm({
3421
3752
  workflow,
3422
3753
  stateCode,
@@ -3427,7 +3758,7 @@ function StateForm({
3427
3758
  onRequestDelete
3428
3759
  }) {
3429
3760
  const messages = useMessages();
3430
- const [renameError, setRenameError] = useState6(null);
3761
+ const [renameError, setRenameError] = useState7(null);
3431
3762
  const outgoing = state.transitions.length;
3432
3763
  const incoming = Object.values(workflow.states).reduce(
3433
3764
  (n, s) => n + s.transitions.filter((t) => t.next === stateCode).length,
@@ -3450,8 +3781,8 @@ function StateForm({
3450
3781
  }
3451
3782
  onDispatch({ op: "renameState", workflow: workflow.name, from: stateCode, to: next });
3452
3783
  };
3453
- return /* @__PURE__ */ jsxs7(FieldGroup, { title: messages.inspector.properties, children: [
3454
- /* @__PURE__ */ jsx8(
3784
+ return /* @__PURE__ */ jsxs9(FieldGroup, { title: messages.inspector.properties, children: [
3785
+ /* @__PURE__ */ jsx10(
3455
3786
  TextField,
3456
3787
  {
3457
3788
  label: messages.inspector.name,
@@ -3462,29 +3793,29 @@ function StateForm({
3462
3793
  testId: "inspector-state-name"
3463
3794
  }
3464
3795
  ),
3465
- renameError && /* @__PURE__ */ jsx8("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
3466
- (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3467
- isInitial && /* @__PURE__ */ jsx8(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
3468
- isTerminal && /* @__PURE__ */ jsx8(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
3469
- isUnreachable && /* @__PURE__ */ jsx8(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
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" })
3470
3801
  ] }),
3471
- /* @__PURE__ */ jsxs7("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3802
+ /* @__PURE__ */ jsxs9("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3472
3803
  outgoing,
3473
3804
  " outgoing \xB7 ",
3474
3805
  incoming,
3475
3806
  " incoming"
3476
3807
  ] }),
3477
- !isInitial && !disabled && /* @__PURE__ */ jsx8(
3808
+ !isInitial && !disabled && /* @__PURE__ */ jsx10(
3478
3809
  "button",
3479
3810
  {
3480
3811
  type: "button",
3481
3812
  onClick: () => onDispatch({ op: "setInitialState", workflow: workflow.name, stateCode }),
3482
- style: ghostBtn,
3813
+ style: ghostBtn2,
3483
3814
  "data-testid": "inspector-state-set-initial",
3484
3815
  children: "Set as Initial State"
3485
3816
  }
3486
3817
  ),
3487
- issues && issues.length > 0 && /* @__PURE__ */ jsx8("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx8(
3818
+ issues && issues.length > 0 && /* @__PURE__ */ jsx10("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx10(
3488
3819
  "div",
3489
3820
  {
3490
3821
  role: "alert",
@@ -3500,21 +3831,31 @@ function StateForm({
3500
3831
  },
3501
3832
  `${issue.code}-${i}`
3502
3833
  )) }),
3503
- /* @__PURE__ */ jsx8(
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(
3504
3845
  "button",
3505
3846
  {
3506
3847
  type: "button",
3507
3848
  onClick: onRequestDelete,
3508
3849
  disabled,
3509
3850
  "data-testid": "inspector-state-delete",
3510
- style: dangerBtn,
3851
+ style: dangerBtn2,
3511
3852
  children: "Delete state\u2026"
3512
3853
  }
3513
3854
  )
3514
3855
  ] });
3515
3856
  }
3516
3857
  function StateBadge({ color, bg, label }) {
3517
- return /* @__PURE__ */ jsx8(
3858
+ return /* @__PURE__ */ jsx10(
3518
3859
  "span",
3519
3860
  {
3520
3861
  style: {
@@ -3546,7 +3887,7 @@ function reachableStates(wf) {
3546
3887
  }
3547
3888
  return visited;
3548
3889
  }
3549
- var ghostBtn = {
3890
+ var ghostBtn2 = {
3550
3891
  alignSelf: "flex-start",
3551
3892
  padding: "5px 10px",
3552
3893
  background: "white",
@@ -3555,7 +3896,7 @@ var ghostBtn = {
3555
3896
  fontSize: 13,
3556
3897
  cursor: "pointer"
3557
3898
  };
3558
- var dangerBtn = {
3899
+ var dangerBtn2 = {
3559
3900
  alignSelf: "flex-start",
3560
3901
  padding: "6px 10px",
3561
3902
  background: colors.dangerBg,
@@ -3567,65 +3908,229 @@ var dangerBtn = {
3567
3908
  };
3568
3909
 
3569
3910
  // src/inspector/TransitionForm.tsx
3570
- import { useRef as useRef7, useState as useState9 } from "react";
3911
+ import { useRef as useRef9, useState as useState10 } from "react";
3571
3912
  import { NAME_REGEX as NAME_REGEX3 } from "@cyoda/workflow-core";
3572
3913
 
3573
- // src/inspector/CriterionForm.tsx
3574
- import { useState as useState7 } from "react";
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";
3575
3917
 
3576
- // src/modals/DeleteStateModal.tsx
3577
- import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef5 } from "react";
3578
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3579
- function countAffected(doc, workflow, stateCode) {
3580
- let outgoing = 0;
3581
- let incoming = 0;
3582
- const wf = doc.session.workflows.find((w) => w.name === workflow);
3583
- if (!wf) return { outgoing, incoming };
3584
- for (const [code, state] of Object.entries(wf.states)) {
3585
- for (const t of state.transitions) {
3586
- if (code === stateCode) outgoing++;
3587
- if (t.next === stateCode && code !== stateCode) incoming++;
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;
3588
3948
  }
3589
3949
  }
3590
- return { outgoing, incoming };
3950
+ return { criterion: null, error: friendly ?? zodMessage(res.error) };
3591
3951
  }
3592
- function DeleteStateModal({
3593
- document: doc,
3594
- workflow,
3595
- stateCode,
3596
- onConfirm,
3597
- onCancel
3598
- }) {
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 }) {
3599
3971
  const messages = useMessages();
3600
- const counts = useMemo3(
3601
- () => countAffected(doc, workflow, stateCode),
3602
- [doc, workflow, stateCode]
3603
- );
3604
- return /* @__PURE__ */ jsxs8(ModalFrame, { onCancel, children: [
3605
- /* @__PURE__ */ jsx9("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
3606
- /* @__PURE__ */ jsx9("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
3607
- /* @__PURE__ */ jsxs8("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
3608
- /* @__PURE__ */ jsx9("strong", { children: stateCode }),
3609
- /* @__PURE__ */ jsxs8("div", { style: { color: colors.textSecondary }, children: [
3610
- messages.confirmDelete.transitionsAffected,
3611
- ": ",
3612
- counts.outgoing + counts.incoming
3613
- ] })
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 })
3614
4010
  ] }),
3615
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
3616
- /* @__PURE__ */ jsx9("button", { type: "button", onClick: onCancel, style: ghostBtn2, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
3617
- /* @__PURE__ */ jsx9("button", { type: "button", onClick: onConfirm, style: dangerBtn2, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
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
+ ] })
3618
4032
  ] })
3619
4033
  ] });
3620
4034
  }
3621
- function ModalFrame({
3622
- children,
3623
- onCancel,
3624
- labelledBy
3625
- }) {
3626
- const frameRef = useRef5(null);
3627
- const previousFocusRef = useRef5(null);
3628
- useEffect3(() => {
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,
4064
+ {
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 })
4071
+ }
4072
+ );
4073
+ }
4074
+
4075
+ // src/inspector/ProcessorForm.tsx
4076
+ import { useEffect as useEffect7, useState as useState9 } from "react";
4077
+ import {
4078
+ NAME_REGEX as NAME_REGEX2
4079
+ } from "@cyoda/workflow-core";
4080
+
4081
+ // src/modals/DeleteStateModal.tsx
4082
+ import { useEffect as useEffect6, useMemo as useMemo3, useRef as useRef8 } from "react";
4083
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
4084
+ function countAffected(doc, workflow, stateCode) {
4085
+ let outgoing = 0;
4086
+ let incoming = 0;
4087
+ const wf = doc.session.workflows.find((w) => w.name === workflow);
4088
+ if (!wf) return { outgoing, incoming };
4089
+ for (const [code, state] of Object.entries(wf.states)) {
4090
+ for (const t of state.transitions) {
4091
+ if (code === stateCode) outgoing++;
4092
+ if (t.next === stateCode && code !== stateCode) incoming++;
4093
+ }
4094
+ }
4095
+ return { outgoing, incoming };
4096
+ }
4097
+ function DeleteStateModal({
4098
+ document: doc,
4099
+ workflow,
4100
+ stateCode,
4101
+ onConfirm,
4102
+ onCancel
4103
+ }) {
4104
+ const messages = useMessages();
4105
+ const counts = useMemo3(
4106
+ () => countAffected(doc, workflow, stateCode),
4107
+ [doc, workflow, stateCode]
4108
+ );
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: [
4115
+ messages.confirmDelete.transitionsAffected,
4116
+ ": ",
4117
+ counts.outgoing + counts.incoming
4118
+ ] })
4119
+ ] }),
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 })
4123
+ ] })
4124
+ ] });
4125
+ }
4126
+ function ModalFrame({
4127
+ children,
4128
+ onCancel,
4129
+ labelledBy
4130
+ }) {
4131
+ const frameRef = useRef8(null);
4132
+ const previousFocusRef = useRef8(null);
4133
+ useEffect6(() => {
3629
4134
  previousFocusRef.current = document.activeElement ?? null;
3630
4135
  const node = frameRef.current;
3631
4136
  if (node) {
@@ -3638,7 +4143,7 @@ function ModalFrame({
3638
4143
  previousFocusRef.current?.focus?.();
3639
4144
  };
3640
4145
  }, []);
3641
- return /* @__PURE__ */ jsx9(
4146
+ return /* @__PURE__ */ jsx13(
3642
4147
  "div",
3643
4148
  {
3644
4149
  onClick: onCancel,
@@ -3658,7 +4163,7 @@ function ModalFrame({
3658
4163
  zIndex: 1e3
3659
4164
  },
3660
4165
  "data-testid": "modal-backdrop",
3661
- children: /* @__PURE__ */ jsx9(
4166
+ children: /* @__PURE__ */ jsx13(
3662
4167
  "div",
3663
4168
  {
3664
4169
  ref: frameRef,
@@ -3684,7 +4189,7 @@ function ModalFrame({
3684
4189
  }
3685
4190
  );
3686
4191
  }
3687
- var ghostBtn2 = {
4192
+ var ghostBtn3 = {
3688
4193
  padding: "6px 12px",
3689
4194
  background: "white",
3690
4195
  border: `1px solid ${colors.border}`,
@@ -3692,460 +4197,15 @@ var ghostBtn2 = {
3692
4197
  fontSize: 13,
3693
4198
  cursor: "pointer"
3694
4199
  };
3695
- var dangerBtn2 = {
3696
- ...ghostBtn2,
3697
- background: colors.danger,
3698
- color: "white",
3699
- borderColor: colors.danger
3700
- };
3701
-
3702
- // src/inspector/CriterionJsonEditor.tsx
3703
- import { useEffect as useEffect4, useRef as useRef6 } from "react";
3704
- import {
3705
- registerCriterionSchema
3706
- } from "@cyoda/workflow-monaco";
3707
-
3708
- // src/inspector/CriterionMonacoContext.tsx
3709
- import { createContext as createContext3, useContext as useContext4 } from "react";
3710
- var CriterionMonacoContext = createContext3(null);
3711
- var CriterionMonacoProvider = CriterionMonacoContext.Provider;
3712
- function useCriterionMonaco() {
3713
- return useContext4(CriterionMonacoContext);
3714
- }
3715
-
3716
- // src/components/monacoDisposal.ts
3717
- var installed = false;
3718
- function isMonacoCanceled(reason) {
3719
- if (reason == null || typeof reason !== "object") return false;
3720
- return reason.name === "Canceled";
3721
- }
3722
- function installMonacoCancellationFilter() {
3723
- if (installed || typeof window === "undefined") return;
3724
- installed = true;
3725
- window.addEventListener("unhandledrejection", (e) => {
3726
- if (isMonacoCanceled(e.reason)) e.preventDefault();
3727
- });
3728
- }
3729
- installMonacoCancellationFilter();
3730
-
3731
- // src/inspector/criterionJson.ts
3732
- import { CriterionSchema, criterionBlockingError } from "@cyoda/workflow-core";
3733
- function criterionModelUri(key) {
3734
- return `cyoda://criterion/${key}.json`;
3735
- }
3736
- function zodMessage(error) {
3737
- const first = error.issues[0];
3738
- if (!first) return "Invalid criterion.";
3739
- const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3740
- return `${first.message}${path}`;
3741
- }
3742
- function parseCriterionJson(text) {
3743
- let raw;
3744
- try {
3745
- raw = JSON.parse(text);
3746
- } catch {
3747
- return { criterion: null, error: "Invalid JSON." };
3748
- }
3749
- const res = CriterionSchema.safeParse(raw);
3750
- if (res.success) {
3751
- const blocking = criterionBlockingError(res.data);
3752
- if (blocking) return { criterion: null, error: blocking };
3753
- return { criterion: res.data, error: null };
3754
- }
3755
- let friendly = null;
3756
- if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3757
- try {
3758
- friendly = criterionBlockingError(raw);
3759
- } catch {
3760
- friendly = null;
3761
- }
3762
- }
3763
- return { criterion: null, error: friendly ?? zodMessage(res.error) };
3764
- }
3765
-
3766
- // src/inspector/CriterionJsonEditor.tsx
3767
- import { jsx as jsx10 } from "react/jsx-runtime";
3768
- function CriterionJsonEditor({ value, disabled, modelKey, onChange }) {
3769
- const monaco = useCriterionMonaco();
3770
- const onChangeRef = useRef6(onChange);
3771
- onChangeRef.current = onChange;
3772
- const initialText = useRef6(JSON.stringify(value, null, 2)).current;
3773
- if (monaco) {
3774
- return /* @__PURE__ */ jsx10(
3775
- MonacoCriterionEditor,
3776
- {
3777
- monaco,
3778
- initialText,
3779
- disabled,
3780
- modelKey,
3781
- onChangeRef
3782
- }
3783
- );
3784
- }
3785
- return /* @__PURE__ */ jsx10(
3786
- TextareaCriterionEditor,
3787
- {
3788
- initialText,
3789
- disabled,
3790
- onChangeRef
3791
- }
3792
- );
3793
- }
3794
- function TextareaCriterionEditor({
3795
- initialText,
3796
- disabled,
3797
- onChangeRef
3798
- }) {
3799
- useEffect4(() => {
3800
- onChangeRef.current(parseCriterionJson(initialText));
3801
- }, [initialText, onChangeRef]);
3802
- return /* @__PURE__ */ jsx10(
3803
- "textarea",
3804
- {
3805
- defaultValue: initialText,
3806
- disabled,
3807
- rows: 16,
3808
- "data-testid": "criterion-json-editor",
3809
- style: jsonTextAreaStyle,
3810
- onChange: (e) => onChangeRef.current(parseCriterionJson(e.target.value))
3811
- }
3812
- );
3813
- }
3814
- function MonacoCriterionEditor({
3815
- monaco,
3816
- initialText,
3817
- disabled,
3818
- modelKey,
3819
- onChangeRef
3820
- }) {
3821
- const containerRef = useRef6(null);
3822
- const editorRef = useRef6(null);
3823
- useEffect4(() => {
3824
- if (!containerRef.current || editorRef.current) return;
3825
- const model = monaco.editor.createModel(
3826
- initialText,
3827
- "json",
3828
- monaco.Uri.parse(criterionModelUri(modelKey))
3829
- );
3830
- const editor = monaco.editor.create(containerRef.current, {
3831
- model,
3832
- automaticLayout: true,
3833
- minimap: { enabled: false },
3834
- fontSize: 13,
3835
- tabSize: 2,
3836
- scrollBeyondLastLine: false,
3837
- theme: "vs",
3838
- readOnly: disabled
3839
- });
3840
- editorRef.current = editor;
3841
- installMonacoCancellationFilter();
3842
- const schemaHandle = registerCriterionSchema(monaco);
3843
- const report = () => onChangeRef.current(parseCriterionJson(model.getValue()));
3844
- report();
3845
- const sub = model.onDidChangeContent(report);
3846
- return () => {
3847
- sub.dispose();
3848
- schemaHandle.dispose();
3849
- editor.dispose();
3850
- editorRef.current = null;
3851
- model.dispose();
3852
- };
3853
- }, [monaco, modelKey]);
3854
- useEffect4(() => {
3855
- editorRef.current?.updateOptions?.({ readOnly: disabled });
3856
- }, [disabled]);
3857
- return /* @__PURE__ */ jsx10(
3858
- "div",
3859
- {
3860
- ref: containerRef,
3861
- "data-testid": "criterion-json-editor",
3862
- style: { height: 320, border: `1px solid ${colors.border}`, borderRadius: radii.sm }
3863
- }
3864
- );
3865
- }
3866
- var jsonTextAreaStyle = {
3867
- fontFamily: fonts.mono,
3868
- fontSize: 12,
3869
- padding: 8,
3870
- borderWidth: 1,
3871
- borderStyle: "solid",
3872
- borderColor: colors.border,
3873
- borderRadius: radii.sm,
3874
- background: "white",
3875
- resize: "vertical"
3876
- };
3877
-
3878
- // src/inspector/CriterionForm.tsx
3879
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
3880
- function defaultCriterion(type) {
3881
- switch (type) {
3882
- case "simple":
3883
- return { type: "simple", jsonPath: "", operation: "EQUALS" };
3884
- case "group":
3885
- return { type: "group", operator: "AND", conditions: [] };
3886
- case "function":
3887
- return { type: "function", function: { name: "" } };
3888
- case "lifecycle":
3889
- return { type: "lifecycle", field: "state", operation: "EQUALS" };
3890
- case "array":
3891
- return { type: "array", jsonPath: "", operation: "EQUALS", value: [] };
3892
- }
3893
- }
3894
- function CriterionSection({
3895
- host,
3896
- stateCode,
3897
- transitionName,
3898
- targetState,
3899
- manual,
3900
- criterion,
3901
- disabled,
3902
- onDispatch,
3903
- onSelectionChange
3904
- }) {
3905
- const messages = useMessages();
3906
- const [modalOpen, setModalOpen] = useState7(false);
3907
- const path = ["criterion"];
3908
- const removeCriterion = () => {
3909
- onDispatch({ op: "setCriterion", host, path, criterion: void 0 });
3910
- if (host.kind === "transition") {
3911
- onSelectionChange?.({ kind: "transition", transitionUuid: host.transitionUuid });
3912
- }
3913
- };
3914
- return /* @__PURE__ */ jsxs9(Fragment4, { children: [
3915
- /* @__PURE__ */ jsx11(
3916
- CriterionSummaryCard,
3917
- {
3918
- criterion,
3919
- disabled,
3920
- manual,
3921
- onAdd: () => setModalOpen(true),
3922
- onEdit: () => setModalOpen(true),
3923
- onRemove: removeCriterion
3924
- }
3925
- ),
3926
- modalOpen && /* @__PURE__ */ jsx11(
3927
- CriterionEditorModal,
3928
- {
3929
- title: criterion ? messages.criterion.editTitle : messages.criterion.addTitle,
3930
- context: `${stateCode ?? host.workflow} \u2192 ${transitionName ?? "transition"} \u2192 ${targetState ?? ""}`,
3931
- host,
3932
- path,
3933
- initialCriterion: criterion,
3934
- disabled,
3935
- onDispatch,
3936
- onCancel: () => setModalOpen(false),
3937
- onApplied: () => {
3938
- setModalOpen(false);
3939
- if (host.kind === "transition") {
3940
- const selection = {
3941
- kind: "transition",
3942
- transitionUuid: host.transitionUuid
3943
- };
3944
- onSelectionChange?.(selection);
3945
- window.setTimeout(() => onSelectionChange?.(selection), 100);
3946
- }
3947
- }
3948
- }
3949
- )
3950
- ] });
3951
- }
3952
- function CriterionSummaryCard({
3953
- criterion,
3954
- disabled,
3955
- manual,
3956
- onAdd,
3957
- onEdit,
3958
- onRemove
3959
- }) {
3960
- const messages = useMessages();
3961
- const m = messages.criterion;
3962
- if (!criterion) {
3963
- return /* @__PURE__ */ jsxs9("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3964
- /* @__PURE__ */ jsx11(SectionHeader, { label: m.heading, badge: "none" }),
3965
- /* @__PURE__ */ jsx11("p", { style: summaryTextStyle, children: manual ? m.noneManual : m.noneAutomated }),
3966
- !manual && /* @__PURE__ */ jsx11("p", { style: warningCardStyle, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3967
- !disabled && /* @__PURE__ */ jsx11(
3968
- "button",
3969
- {
3970
- type: "button",
3971
- onClick: onAdd,
3972
- style: primaryBtn,
3973
- "data-testid": "inspector-criterion-add",
3974
- children: m.add
3975
- }
3976
- )
3977
- ] });
3978
- }
3979
- return /* @__PURE__ */ jsxs9("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3980
- /* @__PURE__ */ jsx11(SectionHeader, { label: m.heading, badge: criterion.type }),
3981
- /* @__PURE__ */ jsx11(CriterionCompactJson, { criterion }),
3982
- !disabled && /* @__PURE__ */ jsxs9("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [
3983
- /* @__PURE__ */ jsx11(
3984
- "button",
3985
- {
3986
- type: "button",
3987
- onClick: onEdit,
3988
- style: ghostBtn3,
3989
- "data-testid": "inspector-criterion-edit",
3990
- children: m.edit
3991
- }
3992
- ),
3993
- /* @__PURE__ */ jsx11(
3994
- "button",
3995
- {
3996
- type: "button",
3997
- onClick: onRemove,
3998
- style: dangerBtn3,
3999
- "data-testid": "inspector-criterion-remove",
4000
- children: m.remove
4001
- }
4002
- )
4003
- ] })
4004
- ] });
4005
- }
4006
- function CriterionCompactJson({ criterion }) {
4007
- const text = JSON.stringify(criterion);
4008
- const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
4009
- return /* @__PURE__ */ jsx11(
4010
- "code",
4011
- {
4012
- "data-testid": "criterion-compact-json",
4013
- style: {
4014
- display: "block",
4015
- fontFamily: fonts.mono,
4016
- fontSize: 11,
4017
- color: colors.textSecondary,
4018
- background: colors.surfaceMuted,
4019
- padding: "6px 8px",
4020
- borderRadius: radii.sm,
4021
- whiteSpace: "pre-wrap",
4022
- wordBreak: "break-word"
4023
- },
4024
- children: display
4025
- }
4026
- );
4027
- }
4028
- function criterionModelKey(host) {
4029
- if (host.kind === "transition") return `transition-${host.transitionUuid}`;
4030
- if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
4031
- return `host-${host.workflow}`;
4032
- }
4033
- function CriterionEditorModal({
4034
- title,
4035
- context,
4036
- host,
4037
- path,
4038
- initialCriterion,
4039
- disabled,
4040
- onDispatch,
4041
- onCancel,
4042
- onApplied
4043
- }) {
4044
- const messages = useMessages();
4045
- const seed = initialCriterion ?? defaultCriterion("simple");
4046
- const [result, setResult] = useState7(
4047
- () => parseCriterionJson(JSON.stringify(seed))
4048
- );
4049
- const modelKey = criterionModelKey(host);
4050
- const applyDisabled = disabled || result.criterion === null;
4051
- const apply = () => {
4052
- if (applyDisabled || !result.criterion) return;
4053
- onDispatch({ op: "setCriterion", host, path, criterion: result.criterion });
4054
- onApplied();
4055
- };
4056
- return /* @__PURE__ */ jsx11(ModalFrame, { onCancel, labelledBy: "criterion-modal-title", children: /* @__PURE__ */ jsxs9("div", { style: modalStyle, "data-testid": "criterion-editor-modal", children: [
4057
- /* @__PURE__ */ jsxs9("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4058
- /* @__PURE__ */ jsx11("h2", { id: "criterion-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4059
- /* @__PURE__ */ jsx11("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: context })
4060
- ] }),
4061
- /* @__PURE__ */ jsx11("div", { style: modalBodyStyle, children: /* @__PURE__ */ jsx11(
4062
- CriterionJsonEditor,
4063
- {
4064
- value: seed,
4065
- disabled,
4066
- modelKey,
4067
- onChange: setResult
4068
- }
4069
- ) }),
4070
- result.error && /* @__PURE__ */ jsx11("div", { role: "alert", style: errorStyle, "data-testid": "criterion-modal-blocking-error", children: result.error }),
4071
- /* @__PURE__ */ jsxs9("footer", { style: modalFooterStyle, children: [
4072
- /* @__PURE__ */ jsx11("div", { style: { flex: 1 } }),
4073
- /* @__PURE__ */ jsx11("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "criterion-modal-cancel", children: messages.criterion.cancel }),
4074
- /* @__PURE__ */ jsx11(
4075
- "button",
4076
- {
4077
- type: "button",
4078
- onClick: apply,
4079
- disabled: applyDisabled,
4080
- style: applyDisabled ? disabledPrimaryBtn : primaryBtn,
4081
- "data-testid": "criterion-modal-apply",
4082
- children: messages.criterion.applyModal
4083
- }
4084
- )
4085
- ] })
4086
- ] }) });
4087
- }
4088
- function SectionHeader({ label, badge }) {
4089
- return /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
4090
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: label }),
4091
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 11, padding: "1px 6px", background: colors.surfaceMuted, borderRadius: radii.pill, color: colors.textTertiary }, children: badge })
4092
- ] });
4093
- }
4094
- var cardStyle = {
4095
- display: "flex",
4096
- flexDirection: "column",
4097
- gap: 8,
4098
- padding: 10,
4099
- border: `1px solid ${colors.border}`,
4100
- borderRadius: radii.md,
4101
- background: "white"
4102
- };
4103
- var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
4104
- var warningCardStyle = {
4105
- margin: 0,
4106
- padding: "6px 8px",
4107
- background: colors.warningBg,
4108
- border: `1px solid ${colors.warningBorder}`,
4109
- borderRadius: radii.sm,
4110
- color: colors.warning,
4111
- fontSize: 11
4112
- };
4113
- var modalStyle = {
4114
- width: "min(760px, calc(100vw - 48px))",
4115
- maxHeight: "min(760px, calc(100vh - 72px))",
4116
- display: "flex",
4117
- flexDirection: "column",
4118
- gap: 14
4119
- };
4120
- var modalBodyStyle = {
4121
- overflow: "auto",
4122
- padding: 12,
4123
- border: `1px solid ${colors.borderSubtle}`,
4124
- borderRadius: radii.md,
4125
- background: colors.surfaceMuted
4126
- };
4127
- var modalFooterStyle = {
4128
- display: "flex",
4129
- alignItems: "center",
4130
- gap: 8,
4131
- position: "sticky",
4132
- bottom: 0,
4133
- paddingTop: 10,
4134
- borderTop: `1px solid ${colors.borderSubtle}`,
4135
- background: "white"
4200
+ var dangerBtn3 = {
4201
+ ...ghostBtn3,
4202
+ background: colors.danger,
4203
+ color: "white",
4204
+ borderColor: colors.danger
4136
4205
  };
4137
- var ghostBtn3 = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
4138
- var primaryBtn = { ...ghostBtn3, background: colors.primary, color: "white", borderColor: colors.primary };
4139
- var disabledPrimaryBtn = { ...primaryBtn, opacity: 0.5, cursor: "not-allowed" };
4140
- var dangerBtn3 = { ...ghostBtn3, background: colors.dangerBg, borderColor: colors.dangerBorder, color: colors.danger };
4141
- var errorStyle = { color: colors.danger, fontSize: 11 };
4142
4206
 
4143
4207
  // src/inspector/ProcessorForm.tsx
4144
- import { useEffect as useEffect5, useState as useState8 } from "react";
4145
- import {
4146
- NAME_REGEX as NAME_REGEX2
4147
- } from "@cyoda/workflow-core";
4148
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
4208
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
4149
4209
  var EXECUTION_MODES = [
4150
4210
  "ASYNC_NEW_TX",
4151
4211
  "ASYNC_SAME_TX",
@@ -4242,8 +4302,8 @@ function ProcessorEditorModal({
4242
4302
  onCancel,
4243
4303
  onApply
4244
4304
  }) {
4245
- const [draft, setDraft] = useState8(() => toDraft(initialProcessor));
4246
- useEffect5(() => {
4305
+ const [draft, setDraft] = useState9(() => toDraft(initialProcessor));
4306
+ useEffect7(() => {
4247
4307
  setDraft(toDraft(initialProcessor));
4248
4308
  }, [initialProcessor]);
4249
4309
  const error = validateDraft(draft, existingNames, initialProcessor?.name);
@@ -4251,13 +4311,13 @@ function ProcessorEditorModal({
4251
4311
  if (disabled || error) return;
4252
4312
  onApply(toProcessor(draft));
4253
4313
  };
4254
- return /* @__PURE__ */ jsx12(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ jsxs10("div", { style: modalStyle2, "data-testid": "processor-editor-modal", children: [
4255
- /* @__PURE__ */ jsxs10("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4256
- /* @__PURE__ */ jsx12("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4257
- /* @__PURE__ */ jsx12("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
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." })
4258
4318
  ] }),
4259
- /* @__PURE__ */ jsxs10("div", { style: modalBodyStyle2, children: [
4260
- /* @__PURE__ */ jsx12(FormField, { label: "Name", children: /* @__PURE__ */ jsx12(
4319
+ /* @__PURE__ */ jsxs12("div", { style: modalBodyStyle, children: [
4320
+ /* @__PURE__ */ jsx14(FormField, { label: "Name", children: /* @__PURE__ */ jsx14(
4261
4321
  "input",
4262
4322
  {
4263
4323
  type: "text",
@@ -4267,7 +4327,7 @@ function ProcessorEditorModal({
4267
4327
  style: inputStyle2
4268
4328
  }
4269
4329
  ) }),
4270
- /* @__PURE__ */ jsx12(FormField, { label: "Execution mode", children: /* @__PURE__ */ jsx12(
4330
+ /* @__PURE__ */ jsx14(FormField, { label: "Execution mode", children: /* @__PURE__ */ jsx14(
4271
4331
  CustomSelectInput,
4272
4332
  {
4273
4333
  value: draft.executionMode,
@@ -4276,8 +4336,8 @@ function ProcessorEditorModal({
4276
4336
  testId: "processor-execution-mode"
4277
4337
  }
4278
4338
  ) }),
4279
- /* @__PURE__ */ jsxs10("label", { style: checkboxRowStyle, children: [
4280
- /* @__PURE__ */ jsx12(
4339
+ /* @__PURE__ */ jsxs12("label", { style: checkboxRowStyle, children: [
4340
+ /* @__PURE__ */ jsx14(
4281
4341
  "input",
4282
4342
  {
4283
4343
  type: "checkbox",
@@ -4285,9 +4345,9 @@ function ProcessorEditorModal({
4285
4345
  onChange: (event) => setDraft((current) => ({ ...current, attachEntity: event.target.checked }))
4286
4346
  }
4287
4347
  ),
4288
- /* @__PURE__ */ jsx12("span", { children: "Attach entity" })
4348
+ /* @__PURE__ */ jsx14("span", { children: "Attach entity" })
4289
4349
  ] }),
4290
- /* @__PURE__ */ jsx12(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ jsx12(
4350
+ /* @__PURE__ */ jsx14(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ jsx14(
4291
4351
  "input",
4292
4352
  {
4293
4353
  type: "text",
@@ -4300,7 +4360,7 @@ function ProcessorEditorModal({
4300
4360
  style: inputStyle2
4301
4361
  }
4302
4362
  ) }),
4303
- /* @__PURE__ */ jsx12(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ jsx12(
4363
+ /* @__PURE__ */ jsx14(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ jsx14(
4304
4364
  "input",
4305
4365
  {
4306
4366
  type: "text",
@@ -4312,7 +4372,7 @@ function ProcessorEditorModal({
4312
4372
  style: inputStyle2
4313
4373
  }
4314
4374
  ) }),
4315
- /* @__PURE__ */ jsx12(FormField, { label: "Retry policy", children: /* @__PURE__ */ jsx12(
4375
+ /* @__PURE__ */ jsx14(FormField, { label: "Retry policy", children: /* @__PURE__ */ jsx14(
4316
4376
  "input",
4317
4377
  {
4318
4378
  type: "text",
@@ -4321,8 +4381,8 @@ function ProcessorEditorModal({
4321
4381
  style: inputStyle2
4322
4382
  }
4323
4383
  ) }),
4324
- /* @__PURE__ */ jsxs10("label", { style: checkboxRowStyle, children: [
4325
- /* @__PURE__ */ jsx12(
4384
+ /* @__PURE__ */ jsxs12("label", { style: checkboxRowStyle, children: [
4385
+ /* @__PURE__ */ jsx14(
4326
4386
  "input",
4327
4387
  {
4328
4388
  type: "checkbox",
@@ -4335,9 +4395,9 @@ function ProcessorEditorModal({
4335
4395
  "data-testid": "processor-async-result"
4336
4396
  }
4337
4397
  ),
4338
- /* @__PURE__ */ jsx12("span", { children: "Async result" })
4398
+ /* @__PURE__ */ jsx14("span", { children: "Async result" })
4339
4399
  ] }),
4340
- /* @__PURE__ */ jsx12(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ jsx12(
4400
+ /* @__PURE__ */ jsx14(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ jsx14(
4341
4401
  "input",
4342
4402
  {
4343
4403
  type: "text",
@@ -4352,16 +4412,16 @@ function ProcessorEditorModal({
4352
4412
  }
4353
4413
  ) })
4354
4414
  ] }),
4355
- error && /* @__PURE__ */ jsx12("div", { role: "alert", style: errorStyle2, "data-testid": "processor-modal-error", children: error }),
4356
- /* @__PURE__ */ jsxs10("footer", { style: modalFooterStyle2, children: [
4357
- /* @__PURE__ */ jsx12("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4358
- /* @__PURE__ */ jsx12(
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(
4359
4419
  "button",
4360
4420
  {
4361
4421
  type: "button",
4362
4422
  onClick: apply,
4363
4423
  disabled: disabled || !!error,
4364
- style: disabled || error ? disabledPrimaryBtn2 : primaryBtn2,
4424
+ style: disabled || error ? disabledPrimaryBtn : primaryBtn2,
4365
4425
  "data-testid": "processor-modal-apply",
4366
4426
  children: "Apply processor"
4367
4427
  }
@@ -4373,8 +4433,8 @@ function FormField({
4373
4433
  label,
4374
4434
  children
4375
4435
  }) {
4376
- return /* @__PURE__ */ jsxs10("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4377
- /* @__PURE__ */ jsx12("span", { style: labelStyle2, children: label }),
4436
+ return /* @__PURE__ */ jsxs12("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4437
+ /* @__PURE__ */ jsx14("span", { style: labelStyle2, children: label }),
4378
4438
  children
4379
4439
  ] });
4380
4440
  }
@@ -4388,18 +4448,18 @@ function ProcessorForm({
4388
4448
  onDispatch
4389
4449
  }) {
4390
4450
  const messages = useMessages();
4391
- const [modalOpen, setModalOpen] = useState8(false);
4392
- return /* @__PURE__ */ jsxs10("div", { style: summaryCardStyle, children: [
4393
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4394
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4395
- /* @__PURE__ */ jsx12("strong", { style: { fontSize: 13 }, children: processor.name }),
4396
- /* @__PURE__ */ jsx12("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4451
+ 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) })
4397
4457
  ] }),
4398
- /* @__PURE__ */ jsx12("span", { style: chipStyle, children: processor.type })
4458
+ /* @__PURE__ */ jsx14("span", { style: chipStyle, children: processor.type })
4399
4459
  ] }),
4400
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4401
- /* @__PURE__ */ jsx12("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4402
- /* @__PURE__ */ jsx12(
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(
4403
4463
  "button",
4404
4464
  {
4405
4465
  type: "button",
@@ -4414,7 +4474,7 @@ function ProcessorForm({
4414
4474
  children: messages.inspector.moveUp
4415
4475
  }
4416
4476
  ),
4417
- /* @__PURE__ */ jsx12(
4477
+ /* @__PURE__ */ jsx14(
4418
4478
  "button",
4419
4479
  {
4420
4480
  type: "button",
@@ -4429,7 +4489,7 @@ function ProcessorForm({
4429
4489
  children: messages.inspector.moveDown
4430
4490
  }
4431
4491
  ),
4432
- /* @__PURE__ */ jsx12(
4492
+ /* @__PURE__ */ jsx14(
4433
4493
  "button",
4434
4494
  {
4435
4495
  type: "button",
@@ -4441,7 +4501,7 @@ function ProcessorForm({
4441
4501
  }
4442
4502
  )
4443
4503
  ] }),
4444
- modalOpen && /* @__PURE__ */ jsx12(
4504
+ modalOpen && /* @__PURE__ */ jsx14(
4445
4505
  ProcessorEditorModal,
4446
4506
  {
4447
4507
  title: `Edit ${processor.name}`,
@@ -4478,18 +4538,18 @@ var disabledInputStyle = {
4478
4538
  background: colors.surfaceMuted,
4479
4539
  color: colors.textTertiary
4480
4540
  };
4481
- var modalStyle2 = {
4541
+ var modalStyle = {
4482
4542
  width: "min(760px, calc(100vw - 48px))",
4483
4543
  display: "flex",
4484
4544
  flexDirection: "column",
4485
4545
  gap: 16
4486
4546
  };
4487
- var modalBodyStyle2 = {
4547
+ var modalBodyStyle = {
4488
4548
  display: "grid",
4489
4549
  gridTemplateColumns: "1fr 1fr",
4490
4550
  gap: 12
4491
4551
  };
4492
- var modalFooterStyle2 = {
4552
+ var modalFooterStyle = {
4493
4553
  display: "flex",
4494
4554
  justifyContent: "flex-end",
4495
4555
  gap: 8
@@ -4503,7 +4563,7 @@ var checkboxRowStyle = {
4503
4563
  color: colors.textSecondary,
4504
4564
  cursor: "pointer"
4505
4565
  };
4506
- var errorStyle2 = {
4566
+ var errorStyle3 = {
4507
4567
  padding: "8px 10px",
4508
4568
  border: `1px solid ${colors.dangerBorder}`,
4509
4569
  background: colors.dangerBg,
@@ -4525,7 +4585,7 @@ var primaryBtn2 = {
4525
4585
  color: "white",
4526
4586
  borderColor: colors.primary
4527
4587
  };
4528
- var disabledPrimaryBtn2 = {
4588
+ var disabledPrimaryBtn = {
4529
4589
  ...primaryBtn2,
4530
4590
  opacity: 0.5,
4531
4591
  cursor: "not-allowed"
@@ -4555,7 +4615,7 @@ var summaryCardStyle = {
4555
4615
  };
4556
4616
 
4557
4617
  // src/inspector/TransitionForm.tsx
4558
- import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
4618
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
4559
4619
  function TransitionForm({
4560
4620
  workflow,
4561
4621
  stateCode,
@@ -4570,15 +4630,15 @@ function TransitionForm({
4570
4630
  onSelectionChange
4571
4631
  }) {
4572
4632
  const messages = useMessages();
4573
- const [renameError, setRenameError] = useState9(null);
4574
- const [processorModal, setProcessorModal] = useState9(null);
4575
- const [scheduleDelayDraft, setScheduleDelayDraft] = useState9(
4633
+ const [renameError, setRenameError] = useState10(null);
4634
+ const [processorModal, setProcessorModal] = useState10(null);
4635
+ const [scheduleDelayDraft, setScheduleDelayDraft] = useState10(
4576
4636
  transition.schedule?.delayMs !== void 0 ? String(transition.schedule.delayMs) : ""
4577
4637
  );
4578
- const [scheduleTimeoutDraft, setScheduleTimeoutDraft] = useState9(
4638
+ const [scheduleTimeoutDraft, setScheduleTimeoutDraft] = useState10(
4579
4639
  transition.schedule?.timeoutMs !== void 0 ? String(transition.schedule.timeoutMs) : ""
4580
4640
  );
4581
- const prevTransitionUuidRef = useRef7(transitionUuid);
4641
+ const prevTransitionUuidRef = useRef9(transitionUuid);
4582
4642
  if (prevTransitionUuidRef.current !== transitionUuid) {
4583
4643
  prevTransitionUuidRef.current = transitionUuid;
4584
4644
  setScheduleDelayDraft(
@@ -4676,9 +4736,9 @@ function TransitionForm({
4676
4736
  index: index + 1
4677
4737
  });
4678
4738
  };
4679
- return /* @__PURE__ */ jsxs11("div", { style: transitionFormStyle, children: [
4680
- /* @__PURE__ */ jsxs11(FieldGroup, { title: messages.inspector.properties, children: [
4681
- /* @__PURE__ */ jsx13(
4739
+ return /* @__PURE__ */ jsxs13("div", { style: transitionFormStyle, children: [
4740
+ /* @__PURE__ */ jsxs13(FieldGroup, { title: messages.inspector.properties, children: [
4741
+ /* @__PURE__ */ jsx15(
4682
4742
  TextField,
4683
4743
  {
4684
4744
  label: messages.inspector.name,
@@ -4689,8 +4749,8 @@ function TransitionForm({
4689
4749
  testId: "inspector-transition-name"
4690
4750
  }
4691
4751
  ),
4692
- renameError && /* @__PURE__ */ jsx13("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4693
- !disabled && /* @__PURE__ */ jsx13(
4752
+ renameError && /* @__PURE__ */ jsx15("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4753
+ !disabled && /* @__PURE__ */ jsx15(
4694
4754
  SelectField,
4695
4755
  {
4696
4756
  label: "Source state",
@@ -4710,7 +4770,7 @@ function TransitionForm({
4710
4770
  testId: "inspector-transition-source-state"
4711
4771
  }
4712
4772
  ),
4713
- /* @__PURE__ */ jsx13(
4773
+ /* @__PURE__ */ jsx15(
4714
4774
  SelectField,
4715
4775
  {
4716
4776
  label: "Target state",
@@ -4721,7 +4781,7 @@ function TransitionForm({
4721
4781
  testId: "inspector-transition-next"
4722
4782
  }
4723
4783
  ),
4724
- /* @__PURE__ */ jsx13(
4784
+ /* @__PURE__ */ jsx15(
4725
4785
  SelectField,
4726
4786
  {
4727
4787
  label: messages.inspector.transitionType,
@@ -4735,7 +4795,7 @@ function TransitionForm({
4735
4795
  testId: "inspector-transition-manual"
4736
4796
  }
4737
4797
  ),
4738
- /* @__PURE__ */ jsx13(
4798
+ /* @__PURE__ */ jsx15(
4739
4799
  CheckboxField,
4740
4800
  {
4741
4801
  label: messages.inspector.disabled,
@@ -4745,7 +4805,7 @@ function TransitionForm({
4745
4805
  testId: "inspector-transition-disabled"
4746
4806
  }
4747
4807
  ),
4748
- /* @__PURE__ */ jsx13(
4808
+ /* @__PURE__ */ jsx15(
4749
4809
  AnchorSelect,
4750
4810
  {
4751
4811
  label: messages.inspector.sourceAnchor,
@@ -4756,7 +4816,7 @@ function TransitionForm({
4756
4816
  testId: "inspector-transition-source-anchor"
4757
4817
  }
4758
4818
  ),
4759
- /* @__PURE__ */ jsx13(
4819
+ /* @__PURE__ */ jsx15(
4760
4820
  AnchorSelect,
4761
4821
  {
4762
4822
  label: messages.inspector.targetAnchor,
@@ -4767,12 +4827,12 @@ function TransitionForm({
4767
4827
  testId: "inspector-transition-target-anchor"
4768
4828
  }
4769
4829
  ),
4770
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4771
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 6 }, children: [
4772
- /* @__PURE__ */ jsx13("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
4773
- /* @__PURE__ */ jsx13("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
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 })
4774
4834
  ] }),
4775
- /* @__PURE__ */ jsx13(
4835
+ /* @__PURE__ */ jsx15(
4776
4836
  "p",
4777
4837
  {
4778
4838
  style: {
@@ -4786,8 +4846,8 @@ function TransitionForm({
4786
4846
  }
4787
4847
  )
4788
4848
  ] }),
4789
- /* @__PURE__ */ jsx13("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4790
- /* @__PURE__ */ jsx13(
4849
+ /* @__PURE__ */ jsx15("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4850
+ /* @__PURE__ */ jsx15(
4791
4851
  "button",
4792
4852
  {
4793
4853
  type: "button",
@@ -4798,8 +4858,8 @@ function TransitionForm({
4798
4858
  children: "Delete transition"
4799
4859
  }
4800
4860
  ),
4801
- /* @__PURE__ */ jsx13("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4802
- issues && issues.length > 0 && /* @__PURE__ */ jsx13("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ jsx13(
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(
4803
4863
  "div",
4804
4864
  {
4805
4865
  role: "alert",
@@ -4816,12 +4876,12 @@ function TransitionForm({
4816
4876
  `${issue.code}-${i}`
4817
4877
  )) })
4818
4878
  ] }),
4819
- /* @__PURE__ */ jsx13(
4879
+ /* @__PURE__ */ jsx15(
4820
4880
  TransitionSection,
4821
4881
  {
4822
4882
  title: messages.inspector.criteria,
4823
4883
  testId: "inspector-transition-criteria-section",
4824
- children: /* @__PURE__ */ jsx13(
4884
+ children: /* @__PURE__ */ jsx15(
4825
4885
  CriterionSection,
4826
4886
  {
4827
4887
  host,
@@ -4837,18 +4897,18 @@ function TransitionForm({
4837
4897
  )
4838
4898
  }
4839
4899
  ),
4840
- /* @__PURE__ */ jsxs11(
4900
+ /* @__PURE__ */ jsxs13(
4841
4901
  TransitionSection,
4842
4902
  {
4843
4903
  title: "Scheduled transition",
4844
4904
  testId: "inspector-transition-schedule-section",
4845
4905
  children: [
4846
- /* @__PURE__ */ jsxs11(
4906
+ /* @__PURE__ */ jsxs13(
4847
4907
  "label",
4848
4908
  {
4849
4909
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: 8, fontSize: 12, color: colors.textSecondary, cursor: "pointer" },
4850
4910
  children: [
4851
- /* @__PURE__ */ jsx13(
4911
+ /* @__PURE__ */ jsx15(
4852
4912
  "input",
4853
4913
  {
4854
4914
  type: "checkbox",
@@ -4868,14 +4928,14 @@ function TransitionForm({
4868
4928
  }
4869
4929
  }
4870
4930
  ),
4871
- /* @__PURE__ */ jsx13("span", { children: "Enable schedule" })
4931
+ /* @__PURE__ */ jsx15("span", { children: "Enable schedule" })
4872
4932
  ]
4873
4933
  }
4874
4934
  ),
4875
- transition.schedule !== void 0 && /* @__PURE__ */ jsxs11(Fragment5, { children: [
4876
- /* @__PURE__ */ jsxs11("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4877
- /* @__PURE__ */ jsx13("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
4878
- /* @__PURE__ */ jsx13(
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(
4879
4939
  "input",
4880
4940
  {
4881
4941
  type: "text",
@@ -4891,9 +4951,9 @@ function TransitionForm({
4891
4951
  }
4892
4952
  )
4893
4953
  ] }),
4894
- /* @__PURE__ */ jsxs11("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4895
- /* @__PURE__ */ jsx13("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
4896
- /* @__PURE__ */ jsx13(
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(
4897
4957
  "input",
4898
4958
  {
4899
4959
  type: "text",
@@ -4910,7 +4970,7 @@ function TransitionForm({
4910
4970
  )
4911
4971
  ] })
4912
4972
  ] }),
4913
- /* @__PURE__ */ jsx13(
4973
+ /* @__PURE__ */ jsx15(
4914
4974
  "p",
4915
4975
  {
4916
4976
  style: {
@@ -4930,28 +4990,28 @@ function TransitionForm({
4930
4990
  ]
4931
4991
  }
4932
4992
  ),
4933
- /* @__PURE__ */ jsxs11(
4993
+ /* @__PURE__ */ jsxs13(
4934
4994
  TransitionSection,
4935
4995
  {
4936
4996
  title: messages.inspector.processors,
4937
4997
  testId: "inspector-transition-processes-section",
4938
4998
  children: [
4939
- processorCount === 0 ? /* @__PURE__ */ jsx13("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ jsx13("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ jsxs11(Fragment5, { children: [
4940
- /* @__PURE__ */ jsx13("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
4941
- processors.map((processor, index) => /* @__PURE__ */ jsxs11("div", { style: processorRowStyle, children: [
4942
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
4943
- /* @__PURE__ */ jsxs11("span", { style: processorOrderStyle, 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: [
4944
5004
  index + 1,
4945
5005
  "."
4946
5006
  ] }),
4947
- /* @__PURE__ */ jsx13("span", { style: processorTypeChipStyle, children: processor.type }),
4948
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
4949
- /* @__PURE__ */ jsx13("strong", { style: { fontSize: 13 }, children: processor.name }),
4950
- /* @__PURE__ */ jsx13("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
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) })
4951
5011
  ] })
4952
5012
  ] }),
4953
- /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4954
- /* @__PURE__ */ jsx13(
5013
+ /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5014
+ /* @__PURE__ */ jsx15(
4955
5015
  "button",
4956
5016
  {
4957
5017
  type: "button",
@@ -4966,7 +5026,7 @@ function TransitionForm({
4966
5026
  children: "Edit"
4967
5027
  }
4968
5028
  ),
4969
- /* @__PURE__ */ jsx13(
5029
+ /* @__PURE__ */ jsx15(
4970
5030
  "button",
4971
5031
  {
4972
5032
  type: "button",
@@ -4977,7 +5037,7 @@ function TransitionForm({
4977
5037
  children: "Duplicate"
4978
5038
  }
4979
5039
  ),
4980
- /* @__PURE__ */ jsx13(
5040
+ /* @__PURE__ */ jsx15(
4981
5041
  "button",
4982
5042
  {
4983
5043
  type: "button",
@@ -4993,7 +5053,7 @@ function TransitionForm({
4993
5053
  children: "Move up"
4994
5054
  }
4995
5055
  ),
4996
- /* @__PURE__ */ jsx13(
5056
+ /* @__PURE__ */ jsx15(
4997
5057
  "button",
4998
5058
  {
4999
5059
  type: "button",
@@ -5009,7 +5069,7 @@ function TransitionForm({
5009
5069
  children: "Move down"
5010
5070
  }
5011
5071
  ),
5012
- /* @__PURE__ */ jsx13(
5072
+ /* @__PURE__ */ jsx15(
5013
5073
  "button",
5014
5074
  {
5015
5075
  type: "button",
@@ -5023,7 +5083,7 @@ function TransitionForm({
5023
5083
  ] })
5024
5084
  ] }, processorUuids[index] ?? `${processor.name}-${index}`))
5025
5085
  ] }),
5026
- /* @__PURE__ */ jsx13(
5086
+ /* @__PURE__ */ jsx15(
5027
5087
  "button",
5028
5088
  {
5029
5089
  type: "button",
@@ -5037,7 +5097,18 @@ function TransitionForm({
5037
5097
  ]
5038
5098
  }
5039
5099
  ),
5040
- processorModal && /* @__PURE__ */ jsx13(
5100
+ /* @__PURE__ */ jsx15(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ jsx15(
5101
+ AnnotationsField,
5102
+ {
5103
+ value: transition.annotations,
5104
+ disabled,
5105
+ showLabel: false,
5106
+ modelKey: `transition-${transitionUuid}`,
5107
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid }, annotations }),
5108
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid } })
5109
+ }
5110
+ ) }),
5111
+ processorModal && /* @__PURE__ */ jsx15(
5041
5112
  ProcessorEditorModal,
5042
5113
  {
5043
5114
  title: processorModal.mode === "add" ? "Add processor" : "Edit processor",
@@ -5057,8 +5128,8 @@ function TransitionSection({
5057
5128
  testId,
5058
5129
  children
5059
5130
  }) {
5060
- return /* @__PURE__ */ jsxs11("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5061
- /* @__PURE__ */ jsx13("header", { style: sectionHeaderStyle, children: title }),
5131
+ return /* @__PURE__ */ jsxs13("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5132
+ /* @__PURE__ */ jsx15("header", { style: sectionHeaderStyle, children: title }),
5062
5133
  children
5063
5134
  ] });
5064
5135
  }
@@ -5165,9 +5236,9 @@ function AnchorSelect({
5165
5236
  { value: "left", label: messages.inspector.anchorLeft },
5166
5237
  { value: "left-bottom", label: messages.inspector.anchorLeftBottom }
5167
5238
  ];
5168
- return /* @__PURE__ */ jsxs11("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5169
- /* @__PURE__ */ jsx13("span", { style: { fontWeight: 500 }, children: label }),
5170
- /* @__PURE__ */ jsx13(
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(
5171
5242
  CustomSelectInput,
5172
5243
  {
5173
5244
  value: value ?? "",
@@ -5182,7 +5253,7 @@ function AnchorSelect({
5182
5253
  }
5183
5254
 
5184
5255
  // src/inspector/Inspector.tsx
5185
- import { Fragment as Fragment6, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
5256
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
5186
5257
  function issueKeyForSelection(selection) {
5187
5258
  if (!selection) return null;
5188
5259
  switch (selection.kind) {
@@ -5207,11 +5278,13 @@ function Inspector({
5207
5278
  onSelectionChange,
5208
5279
  onClose,
5209
5280
  onRequestDeleteState,
5210
- width = 384
5281
+ docked,
5282
+ onToggleDock,
5283
+ onMinimize
5211
5284
  }) {
5212
5285
  const messages = useMessages();
5213
5286
  const { developerMode } = useEditorConfig();
5214
- const [tab, setTab] = useState10("properties");
5287
+ const [tab, setTab] = useState11("properties");
5215
5288
  const effectiveTab = developerMode ? tab : "properties";
5216
5289
  const resolved = useMemo4(() => resolveSelection(doc, selection), [doc, selection]);
5217
5290
  const selectionIssueKey = issueKeyForSelection(selection);
@@ -5220,7 +5293,7 @@ function Inspector({
5220
5293
  return issues.filter((i) => i.targetId === selectionIssueKey);
5221
5294
  }, [issues, selectionIssueKey]);
5222
5295
  const breadcrumb = renderBreadcrumb(resolved);
5223
- return /* @__PURE__ */ jsxs12(
5296
+ return /* @__PURE__ */ jsxs14(
5224
5297
  "aside",
5225
5298
  {
5226
5299
  style: {
@@ -5229,16 +5302,17 @@ function Inspector({
5229
5302
  flexDirection: "column",
5230
5303
  background: colors.surfaceMuted,
5231
5304
  borderLeft: `1px solid ${colors.borderSubtle}`,
5232
- flex: `0 0 ${width}px`,
5233
- width,
5234
- minWidth: 360,
5305
+ flex: "1 1 auto",
5306
+ width: "100%",
5307
+ minWidth: 0,
5235
5308
  fontFamily: fonts.sans
5236
5309
  },
5237
5310
  "data-testid": "inspector",
5238
5311
  children: [
5239
- /* @__PURE__ */ jsxs12(
5312
+ /* @__PURE__ */ jsxs14(
5240
5313
  "header",
5241
5314
  {
5315
+ "data-inspector-drag-handle": true,
5242
5316
  style: {
5243
5317
  padding: "10px 12px",
5244
5318
  borderBottom: `1px solid ${colors.borderSubtle}`,
@@ -5249,8 +5323,59 @@ function Inspector({
5249
5323
  gap: 8
5250
5324
  },
5251
5325
  children: [
5252
- /* @__PURE__ */ jsx14("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5253
- onClose && /* @__PURE__ */ jsx14(
5326
+ /* @__PURE__ */ jsx16("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5327
+ onToggleDock && /* @__PURE__ */ jsx16(
5328
+ "button",
5329
+ {
5330
+ type: "button",
5331
+ "aria-label": docked ? messages.inspector.detachPanel : messages.inspector.dockPanel,
5332
+ title: docked ? messages.inspector.detachPanel : messages.inspector.dockPanel,
5333
+ "data-testid": "inspector-dock-toggle",
5334
+ onClick: onToggleDock,
5335
+ style: {
5336
+ width: 24,
5337
+ height: 24,
5338
+ border: `1px solid ${colors.border}`,
5339
+ borderRadius: radii.sm,
5340
+ background: "white",
5341
+ color: colors.textSecondary,
5342
+ cursor: "pointer",
5343
+ display: "inline-flex",
5344
+ alignItems: "center",
5345
+ justifyContent: "center",
5346
+ padding: 0,
5347
+ fontSize: 13
5348
+ },
5349
+ children: docked ? "\u2922" : "\u2921"
5350
+ }
5351
+ ),
5352
+ onMinimize && /* @__PURE__ */ jsx16(
5353
+ "button",
5354
+ {
5355
+ type: "button",
5356
+ "aria-label": messages.inspector.minimize,
5357
+ title: messages.inspector.minimize,
5358
+ "data-testid": "inspector-minimize",
5359
+ onClick: onMinimize,
5360
+ style: {
5361
+ width: 24,
5362
+ height: 24,
5363
+ border: `1px solid ${colors.border}`,
5364
+ borderRadius: radii.sm,
5365
+ background: "white",
5366
+ color: colors.textSecondary,
5367
+ cursor: "pointer",
5368
+ display: "inline-flex",
5369
+ alignItems: "flex-end",
5370
+ justifyContent: "center",
5371
+ padding: "0 0 5px",
5372
+ fontSize: 18,
5373
+ lineHeight: "10px"
5374
+ },
5375
+ children: "\u2013"
5376
+ }
5377
+ ),
5378
+ onClose && /* @__PURE__ */ jsx16(
5254
5379
  "button",
5255
5380
  {
5256
5381
  type: "button",
@@ -5278,8 +5403,8 @@ function Inspector({
5278
5403
  ]
5279
5404
  }
5280
5405
  ),
5281
- developerMode && /* @__PURE__ */ jsxs12("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5282
- /* @__PURE__ */ jsx14(
5406
+ developerMode && /* @__PURE__ */ jsxs14("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5407
+ /* @__PURE__ */ jsx16(
5283
5408
  TabButton,
5284
5409
  {
5285
5410
  active: effectiveTab === "properties",
@@ -5288,7 +5413,7 @@ function Inspector({
5288
5413
  children: messages.inspector.properties
5289
5414
  }
5290
5415
  ),
5291
- /* @__PURE__ */ jsx14(
5416
+ /* @__PURE__ */ jsx16(
5292
5417
  TabButton,
5293
5418
  {
5294
5419
  active: effectiveTab === "json",
@@ -5298,11 +5423,11 @@ function Inspector({
5298
5423
  }
5299
5424
  )
5300
5425
  ] }),
5301
- /* @__PURE__ */ jsxs12("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5302
- effectiveTab === "properties" && /* @__PURE__ */ jsxs12(Fragment6, { children: [
5303
- !resolved && /* @__PURE__ */ jsx14(EmptyState, { message: messages.inspector.empty }),
5304
- resolved?.kind === "workflow" && /* @__PURE__ */ jsx14(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5305
- resolved?.kind === "state" && /* @__PURE__ */ jsx14(
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(
5306
5431
  StateForm,
5307
5432
  {
5308
5433
  workflow: resolved.workflow,
@@ -5315,7 +5440,7 @@ function Inspector({
5315
5440
  },
5316
5441
  `${resolved.workflow.name}:${resolved.stateCode}`
5317
5442
  ),
5318
- resolved?.kind === "transition" && /* @__PURE__ */ jsx14(
5443
+ resolved?.kind === "transition" && /* @__PURE__ */ jsx16(
5319
5444
  TransitionForm,
5320
5445
  {
5321
5446
  workflow: resolved.workflow,
@@ -5332,7 +5457,7 @@ function Inspector({
5332
5457
  },
5333
5458
  resolved.transitionUuid
5334
5459
  ),
5335
- resolved?.kind === "processor" && /* @__PURE__ */ jsx14(
5460
+ resolved?.kind === "processor" && /* @__PURE__ */ jsx16(
5336
5461
  ProcessorForm,
5337
5462
  {
5338
5463
  processor: resolved.processor,
@@ -5346,8 +5471,8 @@ function Inspector({
5346
5471
  resolved.processorUuid
5347
5472
  )
5348
5473
  ] }),
5349
- developerMode && effectiveTab === "json" && /* @__PURE__ */ jsx14(JsonPreview, { document: doc, resolved }),
5350
- selectionIssues.length > 0 && /* @__PURE__ */ jsx14(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5474
+ developerMode && effectiveTab === "json" && /* @__PURE__ */ jsx16(JsonPreview, { document: doc, resolved }),
5475
+ selectionIssues.length > 0 && /* @__PURE__ */ jsx16(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5351
5476
  ] })
5352
5477
  ]
5353
5478
  }
@@ -5370,7 +5495,7 @@ function TabButton({
5370
5495
  children,
5371
5496
  testId
5372
5497
  }) {
5373
- return /* @__PURE__ */ jsx14(
5498
+ return /* @__PURE__ */ jsx16(
5374
5499
  "button",
5375
5500
  {
5376
5501
  type: "button",
@@ -5391,17 +5516,17 @@ function TabButton({
5391
5516
  );
5392
5517
  }
5393
5518
  function EmptyState({ message }) {
5394
- return /* @__PURE__ */ jsx14("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5519
+ return /* @__PURE__ */ jsx16("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5395
5520
  }
5396
5521
  function IssuesList({
5397
5522
  issues,
5398
5523
  title
5399
5524
  }) {
5400
- return /* @__PURE__ */ jsxs12("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5401
- /* @__PURE__ */ jsx14("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
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 }),
5402
5527
  issues.map((issue, i) => {
5403
5528
  const tone = severityTone(issue.severity);
5404
- return /* @__PURE__ */ jsxs12(
5529
+ return /* @__PURE__ */ jsxs14(
5405
5530
  "div",
5406
5531
  {
5407
5532
  style: {
@@ -5412,8 +5537,8 @@ function IssuesList({
5412
5537
  fontSize: 12
5413
5538
  },
5414
5539
  children: [
5415
- /* @__PURE__ */ jsx14("strong", { children: issue.code }),
5416
- /* @__PURE__ */ jsx14("div", { children: issue.message })
5540
+ /* @__PURE__ */ jsx16("strong", { children: issue.code }),
5541
+ /* @__PURE__ */ jsx16("div", { children: issue.message })
5417
5542
  ]
5418
5543
  },
5419
5544
  `${issue.code}-${i}`
@@ -5433,7 +5558,7 @@ function JsonPreview({
5433
5558
  if (resolved.kind === "processor") return JSON.stringify(resolved.processor, null, 2);
5434
5559
  return "";
5435
5560
  }, [doc, resolved]);
5436
- return /* @__PURE__ */ jsx14(
5561
+ return /* @__PURE__ */ jsx16(
5437
5562
  "pre",
5438
5563
  {
5439
5564
  style: {
@@ -5455,8 +5580,221 @@ function JsonPreview({
5455
5580
  );
5456
5581
  }
5457
5582
 
5583
+ // src/inspector/inspectorPlacement.ts
5584
+ var MIN_FLOAT_W = 340;
5585
+ var MIN_FLOAT_H = 260;
5586
+ function clampRect(rect, viewport) {
5587
+ const width = Math.min(Math.max(rect.width, MIN_FLOAT_W), viewport.w);
5588
+ const height = Math.min(Math.max(rect.height, MIN_FLOAT_H), viewport.h);
5589
+ const left = Math.min(Math.max(rect.left, 0), Math.max(0, viewport.w - width));
5590
+ const top = Math.min(Math.max(rect.top, 0), Math.max(0, viewport.h - height));
5591
+ return { left, top, width, height };
5592
+ }
5593
+ function placementStorageKey(base) {
5594
+ return `${base}:inspector`;
5595
+ }
5596
+ function loadPlacement(base) {
5597
+ if (base === null) return null;
5598
+ try {
5599
+ const raw = localStorage.getItem(placementStorageKey(base));
5600
+ if (!raw) return null;
5601
+ const p = JSON.parse(raw);
5602
+ if (p && (p.mode === "docked" || p.mode === "floating" || p.mode === "minimized") && p.rect && typeof p.rect.left === "number" && typeof p.rect.top === "number" && typeof p.rect.width === "number" && typeof p.rect.height === "number") {
5603
+ return p;
5604
+ }
5605
+ return null;
5606
+ } catch {
5607
+ return null;
5608
+ }
5609
+ }
5610
+ function savePlacement(base, p) {
5611
+ if (base === null) return;
5612
+ try {
5613
+ localStorage.setItem(placementStorageKey(base), JSON.stringify(p));
5614
+ } catch {
5615
+ }
5616
+ }
5617
+
5618
+ // src/inspector/InspectorFrame.tsx
5619
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
5620
+ var FLOATING_Z = 40;
5621
+ var MIN_BAR_Z = 50;
5622
+ function InspectorFrame({
5623
+ mode,
5624
+ rect,
5625
+ dockedWidth,
5626
+ onRectChange,
5627
+ onDockedWidthChange,
5628
+ onRestore,
5629
+ onClose,
5630
+ children
5631
+ }) {
5632
+ const messages = useMessages();
5633
+ const startWidthDrag = (e) => {
5634
+ e.preventDefault();
5635
+ const startX = e.clientX;
5636
+ const startW = dockedWidth;
5637
+ const onMove = (ev) => onDockedWidthChange(Math.max(360, startW + (startX - ev.clientX)));
5638
+ const onUp = () => {
5639
+ document.removeEventListener("mousemove", onMove);
5640
+ document.removeEventListener("mouseup", onUp);
5641
+ };
5642
+ document.addEventListener("mousemove", onMove);
5643
+ document.addEventListener("mouseup", onUp);
5644
+ };
5645
+ const viewport = () => ({ w: window.innerWidth, h: window.innerHeight });
5646
+ const startMove = (e) => {
5647
+ const target = e.target;
5648
+ if (target.closest("button")) return;
5649
+ if (!target.closest("[data-inspector-drag-handle]")) return;
5650
+ e.preventDefault();
5651
+ const dx = e.clientX - rect.left;
5652
+ const dy = e.clientY - rect.top;
5653
+ const onMove = (ev) => onRectChange(clampRect({ ...rect, left: ev.clientX - dx, top: ev.clientY - dy }, viewport()));
5654
+ const onUp = () => {
5655
+ document.removeEventListener("mousemove", onMove);
5656
+ document.removeEventListener("mouseup", onUp);
5657
+ };
5658
+ document.addEventListener("mousemove", onMove);
5659
+ document.addEventListener("mouseup", onUp);
5660
+ };
5661
+ const startResize = (e) => {
5662
+ e.preventDefault();
5663
+ e.stopPropagation();
5664
+ const sx = e.clientX, sy = e.clientY, sw = rect.width, sh = rect.height;
5665
+ const onMove = (ev) => onRectChange(clampRect({ ...rect, width: Math.max(MIN_FLOAT_W, sw + (ev.clientX - sx)), height: Math.max(MIN_FLOAT_H, sh + (ev.clientY - sy)) }, viewport()));
5666
+ const onUp = () => {
5667
+ document.removeEventListener("mousemove", onMove);
5668
+ document.removeEventListener("mouseup", onUp);
5669
+ };
5670
+ document.addEventListener("mousemove", onMove);
5671
+ document.addEventListener("mouseup", onUp);
5672
+ };
5673
+ const floating = mode === "floating";
5674
+ const minimized = mode === "minimized";
5675
+ const style = floating || minimized ? {
5676
+ position: "fixed",
5677
+ left: rect.left,
5678
+ top: rect.top,
5679
+ width: rect.width,
5680
+ height: rect.height,
5681
+ zIndex: FLOATING_Z,
5682
+ boxShadow: "0 24px 50px -12px rgba(15,23,42,0.45)",
5683
+ borderRadius: 12,
5684
+ overflow: "hidden",
5685
+ display: minimized ? "none" : "flex"
5686
+ } : { position: "relative", flex: `0 0 ${dockedWidth}px`, width: dockedWidth, height: "100%", display: "flex" };
5687
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
5688
+ mode === "docked" && /* @__PURE__ */ jsx17(
5689
+ "div",
5690
+ {
5691
+ "data-testid": "inspector-resize-handle",
5692
+ onMouseDown: startWidthDrag,
5693
+ style: { width: 3, flexShrink: 0, cursor: "col-resize", background: "transparent", borderLeft: `1px solid ${colors.borderSubtle}`, zIndex: 10 },
5694
+ onMouseEnter: (e) => e.currentTarget.style.background = colors.border,
5695
+ onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
5696
+ }
5697
+ ),
5698
+ /* @__PURE__ */ jsxs15(
5699
+ "div",
5700
+ {
5701
+ "data-testid": "inspector-frame",
5702
+ onMouseDownCapture: floating ? startMove : void 0,
5703
+ style,
5704
+ children: [
5705
+ children,
5706
+ floating && /* @__PURE__ */ jsx17(
5707
+ "div",
5708
+ {
5709
+ "data-testid": "inspector-resize-grip",
5710
+ onMouseDown: startResize,
5711
+ style: { position: "absolute", right: 2, bottom: 2, width: 16, height: 16, cursor: "nwse-resize", zIndex: 5 }
5712
+ }
5713
+ )
5714
+ ]
5715
+ }
5716
+ ),
5717
+ minimized && /* @__PURE__ */ jsxs15(
5718
+ "div",
5719
+ {
5720
+ "data-testid": "inspector-min-bar",
5721
+ onClick: onRestore,
5722
+ title: messages.inspector.restore,
5723
+ style: minBarStyle,
5724
+ 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(
5728
+ "button",
5729
+ {
5730
+ type: "button",
5731
+ "data-testid": "inspector-restore",
5732
+ "aria-label": messages.inspector.restore,
5733
+ title: messages.inspector.restore,
5734
+ onClick: (e) => {
5735
+ e.stopPropagation();
5736
+ onRestore();
5737
+ },
5738
+ style: barBtnStyle,
5739
+ children: "\u2922"
5740
+ }
5741
+ ),
5742
+ onClose && /* @__PURE__ */ jsx17(
5743
+ "button",
5744
+ {
5745
+ type: "button",
5746
+ "data-testid": "inspector-min-close",
5747
+ "aria-label": "Close inspector",
5748
+ title: "Close inspector",
5749
+ onClick: (e) => {
5750
+ e.stopPropagation();
5751
+ onClose();
5752
+ },
5753
+ style: { ...barBtnStyle, fontSize: 16 },
5754
+ children: "\xD7"
5755
+ }
5756
+ )
5757
+ ]
5758
+ }
5759
+ )
5760
+ ] });
5761
+ }
5762
+ var minBarStyle = {
5763
+ position: "fixed",
5764
+ right: 16,
5765
+ bottom: 16,
5766
+ zIndex: MIN_BAR_Z,
5767
+ display: "flex",
5768
+ alignItems: "center",
5769
+ gap: 8,
5770
+ width: 260,
5771
+ height: 40,
5772
+ padding: "0 6px 0 12px",
5773
+ borderRadius: 10,
5774
+ background: "white",
5775
+ border: `1px solid ${colors.border}`,
5776
+ boxShadow: "0 12px 28px -10px rgba(15,23,42,0.4)",
5777
+ cursor: "pointer",
5778
+ userSelect: "none"
5779
+ };
5780
+ var barBtnStyle = {
5781
+ width: 24,
5782
+ height: 24,
5783
+ flex: "0 0 auto",
5784
+ border: `1px solid ${colors.border}`,
5785
+ borderRadius: radii.sm,
5786
+ background: "white",
5787
+ color: colors.textSecondary,
5788
+ cursor: "pointer",
5789
+ display: "inline-flex",
5790
+ alignItems: "center",
5791
+ justifyContent: "center",
5792
+ padding: 0,
5793
+ fontSize: 13
5794
+ };
5795
+
5458
5796
  // src/toolbar/Toolbar.tsx
5459
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5797
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
5460
5798
  function Toolbar({
5461
5799
  derived,
5462
5800
  readOnly,
@@ -5470,7 +5808,7 @@ function Toolbar({
5470
5808
  toolbarEnd
5471
5809
  }) {
5472
5810
  const messages = useMessages();
5473
- return /* @__PURE__ */ jsxs13(
5811
+ return /* @__PURE__ */ jsxs16(
5474
5812
  "footer",
5475
5813
  {
5476
5814
  style: {
@@ -5485,11 +5823,11 @@ function Toolbar({
5485
5823
  },
5486
5824
  "data-testid": "toolbar",
5487
5825
  children: [
5488
- toolbarStart && /* @__PURE__ */ jsx15("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
5489
- toolbarCenter && /* @__PURE__ */ jsx15("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
5490
- !toolbarCenter && /* @__PURE__ */ jsx15("div", { style: { flex: 1 } }),
5491
- /* @__PURE__ */ jsxs13("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
5492
- /* @__PURE__ */ jsx15(
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(
5493
5831
  ValidationPill,
5494
5832
  {
5495
5833
  severity: "error",
@@ -5501,7 +5839,7 @@ function Toolbar({
5501
5839
  testId: "toolbar-errors"
5502
5840
  }
5503
5841
  ),
5504
- /* @__PURE__ */ jsx15(
5842
+ /* @__PURE__ */ jsx18(
5505
5843
  ValidationPill,
5506
5844
  {
5507
5845
  severity: "warning",
@@ -5513,7 +5851,7 @@ function Toolbar({
5513
5851
  testId: "toolbar-warnings"
5514
5852
  }
5515
5853
  ),
5516
- /* @__PURE__ */ jsx15(
5854
+ /* @__PURE__ */ jsx18(
5517
5855
  ValidationPill,
5518
5856
  {
5519
5857
  severity: "info",
@@ -5526,7 +5864,7 @@ function Toolbar({
5526
5864
  }
5527
5865
  )
5528
5866
  ] }),
5529
- onSave && showSaveButton && /* @__PURE__ */ jsx15(
5867
+ onSave && showSaveButton && /* @__PURE__ */ jsx18(
5530
5868
  "button",
5531
5869
  {
5532
5870
  type: "button",
@@ -5537,7 +5875,7 @@ function Toolbar({
5537
5875
  children: messages.toolbar.save
5538
5876
  }
5539
5877
  ),
5540
- toolbarEnd && /* @__PURE__ */ jsx15("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5878
+ toolbarEnd && /* @__PURE__ */ jsx18("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5541
5879
  ]
5542
5880
  }
5543
5881
  );
@@ -5559,7 +5897,7 @@ function ValidationPill({
5559
5897
  const tone = severityTone(severity);
5560
5898
  const interactive = count > 0 && !!onClick;
5561
5899
  const hasIssues = count > 0;
5562
- return /* @__PURE__ */ jsxs13(
5900
+ return /* @__PURE__ */ jsxs16(
5563
5901
  "button",
5564
5902
  {
5565
5903
  type: "button",
@@ -5586,7 +5924,7 @@ function ValidationPill({
5586
5924
  height: 20
5587
5925
  },
5588
5926
  children: [
5589
- /* @__PURE__ */ jsx15("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5927
+ /* @__PURE__ */ jsx18("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5590
5928
  count
5591
5929
  ]
5592
5930
  }
@@ -5610,8 +5948,8 @@ var slotStyle = {
5610
5948
  };
5611
5949
 
5612
5950
  // src/toolbar/IssuesDrawer.tsx
5613
- import { useEffect as useEffect6, useMemo as useMemo5, useRef as useRef8 } from "react";
5614
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
5951
+ import { useEffect as useEffect8, useMemo as useMemo5, useRef as useRef10 } from "react";
5952
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
5615
5953
  function resolveTarget(doc, targetId) {
5616
5954
  if (!targetId) return null;
5617
5955
  const ids = doc.meta.ids;
@@ -5664,8 +6002,8 @@ function IssuesDrawer({
5664
6002
  onJumpTo
5665
6003
  }) {
5666
6004
  const messages = useMessages();
5667
- const ref = useRef8(null);
5668
- useEffect6(() => {
6005
+ const ref = useRef10(null);
6006
+ useEffect8(() => {
5669
6007
  if (!open) return;
5670
6008
  function onKey(e) {
5671
6009
  if (e.key === "Escape") {
@@ -5700,7 +6038,7 @@ function IssuesDrawer({
5700
6038
  }, [severity, messages]);
5701
6039
  const tone = severityTone(severity);
5702
6040
  if (!open) return null;
5703
- return /* @__PURE__ */ jsxs14(
6041
+ return /* @__PURE__ */ jsxs17(
5704
6042
  "div",
5705
6043
  {
5706
6044
  ref,
@@ -5724,7 +6062,7 @@ function IssuesDrawer({
5724
6062
  flexDirection: "column"
5725
6063
  },
5726
6064
  children: [
5727
- /* @__PURE__ */ jsxs14(
6065
+ /* @__PURE__ */ jsxs17(
5728
6066
  "header",
5729
6067
  {
5730
6068
  style: {
@@ -5735,7 +6073,7 @@ function IssuesDrawer({
5735
6073
  gap: 8
5736
6074
  },
5737
6075
  children: [
5738
- /* @__PURE__ */ jsx16(
6076
+ /* @__PURE__ */ jsx19(
5739
6077
  "span",
5740
6078
  {
5741
6079
  style: {
@@ -5748,12 +6086,12 @@ function IssuesDrawer({
5748
6086
  "aria-hidden": true
5749
6087
  }
5750
6088
  ),
5751
- /* @__PURE__ */ jsxs14("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6089
+ /* @__PURE__ */ jsxs17("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
5752
6090
  title,
5753
6091
  " \xB7 ",
5754
6092
  filtered.length
5755
6093
  ] }),
5756
- /* @__PURE__ */ jsx16(
6094
+ /* @__PURE__ */ jsx19(
5757
6095
  "button",
5758
6096
  {
5759
6097
  type: "button",
@@ -5776,14 +6114,14 @@ function IssuesDrawer({
5776
6114
  ]
5777
6115
  }
5778
6116
  ),
5779
- filtered.length === 0 ? /* @__PURE__ */ jsx16(
6117
+ filtered.length === 0 ? /* @__PURE__ */ jsx19(
5780
6118
  "p",
5781
6119
  {
5782
6120
  style: { padding: 12, color: colors.textTertiary, fontSize: 12, margin: 0 },
5783
6121
  "data-testid": "issues-drawer-empty",
5784
6122
  children: messages.issues.none
5785
6123
  }
5786
- ) : /* @__PURE__ */ jsx16(
6124
+ ) : /* @__PURE__ */ jsx19(
5787
6125
  "ul",
5788
6126
  {
5789
6127
  style: {
@@ -5797,7 +6135,7 @@ function IssuesDrawer({
5797
6135
  children: filtered.map((issue, idx) => {
5798
6136
  const target = resolveTarget(doc, issue.targetId);
5799
6137
  const targetLabel = target ? target.kind === "transition" ? `${messages.issues.relatedTransition}: ${target.label}` : target.kind === "state" ? `${messages.issues.relatedState}: ${target.label}` : target.label : null;
5800
- return /* @__PURE__ */ jsxs14(
6138
+ return /* @__PURE__ */ jsxs17(
5801
6139
  "li",
5802
6140
  {
5803
6141
  style: {
@@ -5811,10 +6149,10 @@ function IssuesDrawer({
5811
6149
  },
5812
6150
  "data-testid": `issues-drawer-item-${idx}`,
5813
6151
  children: [
5814
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
5815
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
5816
- targetLabel && /* @__PURE__ */ jsx16("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
5817
- target && /* @__PURE__ */ jsx16("div", { children: /* @__PURE__ */ jsx16(
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(
5818
6156
  "button",
5819
6157
  {
5820
6158
  type: "button",
@@ -5849,23 +6187,23 @@ function IssuesDrawer({
5849
6187
  }
5850
6188
 
5851
6189
  // src/toolbar/WorkflowTabs.tsx
5852
- import { useEffect as useEffect8, useRef as useRef10, useState as useState12 } from "react";
6190
+ import { useEffect as useEffect10, useRef as useRef12, useState as useState13 } from "react";
5853
6191
 
5854
6192
  // src/toolbar/VersionBadge.tsx
5855
- import { useEffect as useEffect7, useRef as useRef9, useState as useState11 } from "react";
6193
+ import { useEffect as useEffect9, useRef as useRef11, useState as useState12 } from "react";
5856
6194
  import { createPortal as createPortal2 } from "react-dom";
5857
- import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
6195
+ import { Fragment as Fragment8, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
5858
6196
  function VersionBadge({
5859
6197
  version,
5860
6198
  supportedVersions,
5861
6199
  readOnly = false,
5862
6200
  onVersionChange
5863
6201
  }) {
5864
- const [open, setOpen] = useState11(false);
5865
- const [dropdownPos, setDropdownPos] = useState11(null);
5866
- const buttonRef = useRef9(null);
5867
- const dropdownRef = useRef9(null);
5868
- useEffect7(() => {
6202
+ const [open, setOpen] = useState12(false);
6203
+ const [dropdownPos, setDropdownPos] = useState12(null);
6204
+ const buttonRef = useRef11(null);
6205
+ const dropdownRef = useRef11(null);
6206
+ useEffect9(() => {
5869
6207
  if (!open) return;
5870
6208
  const handler = (e) => {
5871
6209
  const target = e.target;
@@ -5887,7 +6225,7 @@ function VersionBadge({
5887
6225
  setOpen((o) => !o);
5888
6226
  };
5889
6227
  if (readOnly) {
5890
- return /* @__PURE__ */ jsx17(
6228
+ return /* @__PURE__ */ jsx20(
5891
6229
  "div",
5892
6230
  {
5893
6231
  "data-testid": "version-badge",
@@ -5906,7 +6244,7 @@ function VersionBadge({
5906
6244
  );
5907
6245
  }
5908
6246
  const dropdown = open && dropdownPos ? createPortal2(
5909
- /* @__PURE__ */ jsxs15(
6247
+ /* @__PURE__ */ jsxs18(
5910
6248
  "div",
5911
6249
  {
5912
6250
  ref: dropdownRef,
@@ -5925,7 +6263,7 @@ function VersionBadge({
5925
6263
  zIndex: 9999
5926
6264
  },
5927
6265
  children: [
5928
- /* @__PURE__ */ jsx17(
6266
+ /* @__PURE__ */ jsx20(
5929
6267
  "div",
5930
6268
  {
5931
6269
  style: {
@@ -5942,7 +6280,7 @@ function VersionBadge({
5942
6280
  ),
5943
6281
  [...supportedVersions].reverse().map((v) => {
5944
6282
  const isCurrent = v === version.replace(/^v/, "");
5945
- return /* @__PURE__ */ jsxs15(
6283
+ return /* @__PURE__ */ jsxs18(
5946
6284
  "button",
5947
6285
  {
5948
6286
  type: "button",
@@ -5965,16 +6303,16 @@ function VersionBadge({
5965
6303
  textAlign: "left"
5966
6304
  },
5967
6305
  children: [
5968
- /* @__PURE__ */ jsxs15("span", { children: [
6306
+ /* @__PURE__ */ jsxs18("span", { children: [
5969
6307
  v,
5970
6308
  " ",
5971
- /* @__PURE__ */ jsxs15("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6309
+ /* @__PURE__ */ jsxs18("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
5972
6310
  "cyoda-go ",
5973
6311
  v,
5974
6312
  ".x"
5975
6313
  ] })
5976
6314
  ] }),
5977
- isCurrent && /* @__PURE__ */ jsx17(
6315
+ isCurrent && /* @__PURE__ */ jsx20(
5978
6316
  "span",
5979
6317
  {
5980
6318
  style: {
@@ -5998,8 +6336,8 @@ function VersionBadge({
5998
6336
  ),
5999
6337
  document.body
6000
6338
  ) : null;
6001
- return /* @__PURE__ */ jsxs15(Fragment7, { children: [
6002
- /* @__PURE__ */ jsxs15(
6339
+ return /* @__PURE__ */ jsxs18(Fragment8, { children: [
6340
+ /* @__PURE__ */ jsxs18(
6003
6341
  "button",
6004
6342
  {
6005
6343
  ref: buttonRef,
@@ -6022,7 +6360,7 @@ function VersionBadge({
6022
6360
  },
6023
6361
  children: [
6024
6362
  version,
6025
- /* @__PURE__ */ jsx17("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6363
+ /* @__PURE__ */ jsx20("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6026
6364
  ]
6027
6365
  }
6028
6366
  ),
@@ -6031,7 +6369,7 @@ function VersionBadge({
6031
6369
  }
6032
6370
 
6033
6371
  // src/toolbar/WorkflowTabs.tsx
6034
- import { Fragment as Fragment8, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
6372
+ import { Fragment as Fragment9, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
6035
6373
  function WorkflowTabs({
6036
6374
  workflows,
6037
6375
  activeWorkflow,
@@ -6045,10 +6383,10 @@ function WorkflowTabs({
6045
6383
  onVersionChange
6046
6384
  }) {
6047
6385
  const messages = useMessages();
6048
- const [editingTab, setEditingTab] = useState12(null);
6049
- const [draftName, setDraftName] = useState12("");
6050
- const inputRef = useRef10(null);
6051
- useEffect8(() => {
6386
+ const [editingTab, setEditingTab] = useState13(null);
6387
+ const [draftName, setDraftName] = useState13("");
6388
+ const inputRef = useRef12(null);
6389
+ useEffect10(() => {
6052
6390
  if (editingTab !== null) inputRef.current?.select();
6053
6391
  }, [editingTab]);
6054
6392
  const startEditing = (name) => {
@@ -6068,7 +6406,7 @@ function WorkflowTabs({
6068
6406
  setEditingTab(null);
6069
6407
  };
6070
6408
  const cancelEdit = () => setEditingTab(null);
6071
- return /* @__PURE__ */ jsxs16(
6409
+ return /* @__PURE__ */ jsxs19(
6072
6410
  "nav",
6073
6411
  {
6074
6412
  style: {
@@ -6086,7 +6424,7 @@ function WorkflowTabs({
6086
6424
  workflows.map((w) => {
6087
6425
  const active = w.name === activeWorkflow;
6088
6426
  const isEditing = editingTab === w.name;
6089
- return /* @__PURE__ */ jsxs16(
6427
+ return /* @__PURE__ */ jsxs19(
6090
6428
  "div",
6091
6429
  {
6092
6430
  style: {
@@ -6097,7 +6435,7 @@ function WorkflowTabs({
6097
6435
  background: active ? "white" : "transparent"
6098
6436
  },
6099
6437
  children: [
6100
- isEditing ? /* @__PURE__ */ jsx18(
6438
+ isEditing ? /* @__PURE__ */ jsx21(
6101
6439
  "input",
6102
6440
  {
6103
6441
  ref: inputRef,
@@ -6128,7 +6466,7 @@ function WorkflowTabs({
6128
6466
  width: Math.max(60, draftName.length * 8)
6129
6467
  }
6130
6468
  }
6131
- ) : /* @__PURE__ */ jsx18(
6469
+ ) : /* @__PURE__ */ jsx21(
6132
6470
  "button",
6133
6471
  {
6134
6472
  type: "button",
@@ -6147,7 +6485,7 @@ function WorkflowTabs({
6147
6485
  children: w.name || messages.tabs.untitled
6148
6486
  }
6149
6487
  ),
6150
- onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ jsx18(
6488
+ onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ jsx21(
6151
6489
  "button",
6152
6490
  {
6153
6491
  type: "button",
@@ -6170,7 +6508,7 @@ function WorkflowTabs({
6170
6508
  w.name
6171
6509
  );
6172
6510
  }),
6173
- onAdd && !readOnly && /* @__PURE__ */ jsxs16(
6511
+ onAdd && !readOnly && /* @__PURE__ */ jsxs19(
6174
6512
  "button",
6175
6513
  {
6176
6514
  type: "button",
@@ -6195,9 +6533,9 @@ function WorkflowTabs({
6195
6533
  ]
6196
6534
  }
6197
6535
  ),
6198
- dialectVersion && /* @__PURE__ */ jsxs16(Fragment8, { children: [
6199
- /* @__PURE__ */ jsx18("div", { style: { flex: 1 } }),
6200
- /* @__PURE__ */ jsx18(
6536
+ dialectVersion && /* @__PURE__ */ jsxs19(Fragment9, { children: [
6537
+ /* @__PURE__ */ jsx21("div", { style: { flex: 1 } }),
6538
+ /* @__PURE__ */ jsx21(
6201
6539
  VersionBadge,
6202
6540
  {
6203
6541
  version: dialectVersion,
@@ -6213,9 +6551,9 @@ function WorkflowTabs({
6213
6551
  }
6214
6552
 
6215
6553
  // src/modals/DragConnectModal.tsx
6216
- import { useState as useState13 } from "react";
6554
+ import { useState as useState14 } from "react";
6217
6555
  import { NAME_REGEX as NAME_REGEX4 } from "@cyoda/workflow-core";
6218
- import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
6556
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
6219
6557
  function generateDefault(toState, existing) {
6220
6558
  const base = `to_${toState}`;
6221
6559
  if (!existing.has(base)) return base;
@@ -6232,20 +6570,20 @@ function DragConnectModal({
6232
6570
  }) {
6233
6571
  const messages = useMessages();
6234
6572
  const existing = new Set(source.transitions.map((t) => t.name));
6235
- const [name, setName] = useState13(() => generateDefault(toState, existing));
6573
+ const [name, setName] = useState14(() => generateDefault(toState, existing));
6236
6574
  const invalidFormat = !!name && !NAME_REGEX4.test(name);
6237
6575
  const duplicate = existing.has(name);
6238
6576
  const blocked = name.length === 0 || invalidFormat || duplicate;
6239
- return /* @__PURE__ */ jsxs17(ModalFrame, { onCancel, children: [
6240
- /* @__PURE__ */ jsx19("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6241
- /* @__PURE__ */ jsxs17("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
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: [
6242
6580
  fromState,
6243
6581
  " \u2192 ",
6244
6582
  toState
6245
6583
  ] }),
6246
- /* @__PURE__ */ jsxs17("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6247
- /* @__PURE__ */ jsx19("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6248
- /* @__PURE__ */ jsx19(
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(
6249
6587
  "input",
6250
6588
  {
6251
6589
  type: "text",
@@ -6265,11 +6603,11 @@ function DragConnectModal({
6265
6603
  }
6266
6604
  )
6267
6605
  ] }),
6268
- invalidFormat && /* @__PURE__ */ jsx19("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6269
- duplicate && /* @__PURE__ */ jsx19("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6270
- /* @__PURE__ */ jsxs17("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6271
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6272
- /* @__PURE__ */ jsx19(
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(
6273
6611
  "button",
6274
6612
  {
6275
6613
  type: "button",
@@ -6304,19 +6642,19 @@ var primaryBtn3 = {
6304
6642
  };
6305
6643
 
6306
6644
  // src/modals/AddStateModal.tsx
6307
- import { useEffect as useEffect9, useRef as useRef11, useState as useState14 } from "react";
6645
+ import { useEffect as useEffect11, useRef as useRef13, useState as useState15 } from "react";
6308
6646
  import { NAME_REGEX as NAME_REGEX5 } from "@cyoda/workflow-core";
6309
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
6647
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
6310
6648
  function generateName(existing) {
6311
6649
  let n = 1;
6312
6650
  while (existing.includes(`state${n}`)) n++;
6313
6651
  return `state${n}`;
6314
6652
  }
6315
6653
  function AddStateModal({ existingNames, onCreate, onCancel }) {
6316
- const [name, setName] = useState14(() => generateName(existingNames));
6317
- const [error, setError] = useState14(null);
6318
- const inputRef = useRef11(null);
6319
- useEffect9(() => {
6654
+ const [name, setName] = useState15(() => generateName(existingNames));
6655
+ const [error, setError] = useState15(null);
6656
+ const inputRef = useRef13(null);
6657
+ useEffect11(() => {
6320
6658
  inputRef.current?.select();
6321
6659
  }, []);
6322
6660
  const validate = (v) => {
@@ -6334,11 +6672,11 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6334
6672
  }
6335
6673
  onCreate(name.trim());
6336
6674
  };
6337
- return /* @__PURE__ */ jsxs18(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6338
- /* @__PURE__ */ jsx20("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6339
- /* @__PURE__ */ jsxs18("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6340
- /* @__PURE__ */ jsx20("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6341
- /* @__PURE__ */ jsx20(
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(
6342
6680
  "input",
6343
6681
  {
6344
6682
  ref: inputRef,
@@ -6364,7 +6702,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6364
6702
  }
6365
6703
  }
6366
6704
  ),
6367
- error && /* @__PURE__ */ jsx20(
6705
+ error && /* @__PURE__ */ jsx23(
6368
6706
  "div",
6369
6707
  {
6370
6708
  id: "add-state-error",
@@ -6374,8 +6712,8 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6374
6712
  }
6375
6713
  )
6376
6714
  ] }),
6377
- /* @__PURE__ */ jsxs18("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6378
- /* @__PURE__ */ jsx20(
6715
+ /* @__PURE__ */ jsxs21("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6716
+ /* @__PURE__ */ jsx23(
6379
6717
  "button",
6380
6718
  {
6381
6719
  type: "button",
@@ -6385,7 +6723,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6385
6723
  children: "Cancel"
6386
6724
  }
6387
6725
  ),
6388
- /* @__PURE__ */ jsx20(
6726
+ /* @__PURE__ */ jsx23(
6389
6727
  "button",
6390
6728
  {
6391
6729
  type: "button",
@@ -6415,15 +6753,15 @@ var primaryBtn4 = {
6415
6753
 
6416
6754
  // src/modals/HelpModal.tsx
6417
6755
  import { workflowPalette as workflowPalette5 } from "@cyoda/workflow-viewer/theme";
6418
- import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
6756
+ import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
6419
6757
  function HelpModal({ onCancel }) {
6420
6758
  const messages = useMessages();
6421
6759
  const h = messages.help;
6422
6760
  const node = workflowPalette5.node;
6423
6761
  const edge = workflowPalette5.edge;
6424
- return /* @__PURE__ */ jsx21(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ jsxs19("div", { style: { width: 480, maxWidth: "85vw" }, children: [
6425
- /* @__PURE__ */ jsx21("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
6426
- /* @__PURE__ */ jsxs19(
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(
6427
6765
  "div",
6428
6766
  {
6429
6767
  style: {
@@ -6436,48 +6774,48 @@ function HelpModal({ onCancel }) {
6436
6774
  gap: 16
6437
6775
  },
6438
6776
  children: [
6439
- /* @__PURE__ */ jsxs19(Section, { title: h.statesTitle, children: [
6440
- /* @__PURE__ */ jsx21(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
6441
- /* @__PURE__ */ jsx21(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
6442
- /* @__PURE__ */ jsx21(ColorRow, { fill: node.processing.fill, border: node.processing.border, label: h.stateProcessing }),
6443
- /* @__PURE__ */ jsx21(ColorRow, { fill: node.manualReview.fill, border: node.manualReview.border, label: h.stateManualReview }),
6444
- /* @__PURE__ */ jsx21(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
6445
- /* @__PURE__ */ jsx21(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
6446
- /* @__PURE__ */ jsx21(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
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 })
6447
6785
  ] }),
6448
- /* @__PURE__ */ jsxs19(Section, { title: h.transitionsTitle, children: [
6449
- /* @__PURE__ */ jsx21(LineRow, { color: edge.automated, label: h.transitionAutomated }),
6450
- /* @__PURE__ */ jsx21(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
6451
- /* @__PURE__ */ jsx21(LineRow, { color: edge.conditional, label: h.transitionConditional }),
6452
- /* @__PURE__ */ jsx21(LineRow, { color: edge.processing, label: h.transitionProcessing }),
6453
- /* @__PURE__ */ jsx21(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
6454
- /* @__PURE__ */ jsx21(LineRow, { color: edge.loop, label: h.transitionLoop }),
6455
- /* @__PURE__ */ jsx21(LineRow, { color: edge.disabled, label: h.transitionDisabled })
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 })
6456
6794
  ] }),
6457
- /* @__PURE__ */ jsxs19(Section, { title: h.controlsTitle, children: [
6458
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
6459
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
6460
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
6461
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
6462
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
6463
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
6464
- /* @__PURE__ */ jsx21(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
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 })
6465
6803
  ] }),
6466
- /* @__PURE__ */ jsx21(Section, { title: h.tipsTitle, children: /* @__PURE__ */ jsxs19("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
6467
- /* @__PURE__ */ jsx21("li", { children: h.tipDoubleClick }),
6468
- /* @__PURE__ */ jsx21("li", { children: h.tipConnect }),
6469
- /* @__PURE__ */ jsx21("li", { children: h.tipSelect }),
6470
- /* @__PURE__ */ jsx21("li", { children: h.tipMove })
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 })
6471
6809
  ] }) })
6472
6810
  ]
6473
6811
  }
6474
6812
  ),
6475
- /* @__PURE__ */ jsx21("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ jsx21("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
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 }) })
6476
6814
  ] }) });
6477
6815
  }
6478
6816
  function Section({ title, children }) {
6479
- return /* @__PURE__ */ jsxs19("div", { children: [
6480
- /* @__PURE__ */ jsx21(
6817
+ return /* @__PURE__ */ jsxs22("div", { children: [
6818
+ /* @__PURE__ */ jsx24(
6481
6819
  "h3",
6482
6820
  {
6483
6821
  style: {
@@ -6491,12 +6829,12 @@ function Section({ title, children }) {
6491
6829
  children: title
6492
6830
  }
6493
6831
  ),
6494
- /* @__PURE__ */ jsx21("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6832
+ /* @__PURE__ */ jsx24("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6495
6833
  ] });
6496
6834
  }
6497
6835
  function ColorRow({ fill, border, label }) {
6498
- return /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6499
- /* @__PURE__ */ jsx21(
6836
+ return /* @__PURE__ */ jsxs22("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6837
+ /* @__PURE__ */ jsx24(
6500
6838
  "span",
6501
6839
  {
6502
6840
  style: {
@@ -6509,12 +6847,12 @@ function ColorRow({ fill, border, label }) {
6509
6847
  }
6510
6848
  }
6511
6849
  ),
6512
- /* @__PURE__ */ jsx21("span", { children: label })
6850
+ /* @__PURE__ */ jsx24("span", { children: label })
6513
6851
  ] });
6514
6852
  }
6515
6853
  function LineRow({ color, label, dashed }) {
6516
- return /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6517
- /* @__PURE__ */ jsx21("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ jsx21(
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(
6518
6856
  "line",
6519
6857
  {
6520
6858
  x1: "2",
@@ -6527,12 +6865,12 @@ function LineRow({ color, label, dashed }) {
6527
6865
  ...dashed ? { strokeDasharray: "3 3" } : {}
6528
6866
  }
6529
6867
  ) }),
6530
- /* @__PURE__ */ jsx21("span", { children: label })
6868
+ /* @__PURE__ */ jsx24("span", { children: label })
6531
6869
  ] });
6532
6870
  }
6533
6871
  function ShortcutRow({ keys, label }) {
6534
- return /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6535
- /* @__PURE__ */ jsx21(
6872
+ return /* @__PURE__ */ jsxs22("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6873
+ /* @__PURE__ */ jsx24(
6536
6874
  "kbd",
6537
6875
  {
6538
6876
  style: {
@@ -6552,12 +6890,12 @@ function ShortcutRow({ keys, label }) {
6552
6890
  children: keys
6553
6891
  }
6554
6892
  ),
6555
- /* @__PURE__ */ jsx21("span", { children: label })
6893
+ /* @__PURE__ */ jsx24("span", { children: label })
6556
6894
  ] });
6557
6895
  }
6558
6896
 
6559
6897
  // src/modals/VersionSwitchModal.tsx
6560
- import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
6898
+ import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
6561
6899
  function VersionSwitchModal({
6562
6900
  fromVersion,
6563
6901
  toVersion,
@@ -6565,7 +6903,7 @@ function VersionSwitchModal({
6565
6903
  onConfirm,
6566
6904
  onCancel
6567
6905
  }) {
6568
- return /* @__PURE__ */ jsx22(
6906
+ return /* @__PURE__ */ jsx25(
6569
6907
  "div",
6570
6908
  {
6571
6909
  style: {
@@ -6577,7 +6915,7 @@ function VersionSwitchModal({
6577
6915
  justifyContent: "center",
6578
6916
  zIndex: 1e3
6579
6917
  },
6580
- children: /* @__PURE__ */ jsxs20(
6918
+ children: /* @__PURE__ */ jsxs23(
6581
6919
  "div",
6582
6920
  {
6583
6921
  "data-testid": "version-switch-modal",
@@ -6591,8 +6929,8 @@ function VersionSwitchModal({
6591
6929
  fontFamily: "inherit"
6592
6930
  },
6593
6931
  children: [
6594
- /* @__PURE__ */ jsxs20("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6595
- /* @__PURE__ */ jsx22(
6932
+ /* @__PURE__ */ jsxs23("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6933
+ /* @__PURE__ */ jsx25(
6596
6934
  "div",
6597
6935
  {
6598
6936
  style: {
@@ -6609,20 +6947,20 @@ function VersionSwitchModal({
6609
6947
  children: "\u26A0\uFE0F"
6610
6948
  }
6611
6949
  ),
6612
- /* @__PURE__ */ jsxs20("div", { children: [
6613
- /* @__PURE__ */ jsxs20("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6950
+ /* @__PURE__ */ jsxs23("div", { children: [
6951
+ /* @__PURE__ */ jsxs23("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6614
6952
  "Switch to ",
6615
6953
  toVersion,
6616
6954
  "?"
6617
6955
  ] }),
6618
- /* @__PURE__ */ jsxs20("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6956
+ /* @__PURE__ */ jsxs23("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6619
6957
  "Switching to ",
6620
6958
  toVersion,
6621
6959
  " will remove data not supported in that dialect:"
6622
6960
  ] })
6623
6961
  ] })
6624
6962
  ] }),
6625
- /* @__PURE__ */ jsxs20(
6963
+ /* @__PURE__ */ jsxs23(
6626
6964
  "div",
6627
6965
  {
6628
6966
  style: {
@@ -6635,17 +6973,17 @@ function VersionSwitchModal({
6635
6973
  fontSize: 12
6636
6974
  },
6637
6975
  children: [
6638
- /* @__PURE__ */ jsx22("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
6639
- /* @__PURE__ */ jsx22("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ jsx22("li", { children: w }, i)) })
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)) })
6640
6978
  ]
6641
6979
  }
6642
6980
  ),
6643
- /* @__PURE__ */ jsxs20("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6981
+ /* @__PURE__ */ jsxs23("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6644
6982
  "This cannot be undone. You can switch back to ",
6645
6983
  fromVersion,
6646
6984
  " any time, but the removed data will not be restored."
6647
6985
  ] }),
6648
- /* @__PURE__ */ jsxs20(
6986
+ /* @__PURE__ */ jsxs23(
6649
6987
  "div",
6650
6988
  {
6651
6989
  style: {
@@ -6657,7 +6995,7 @@ function VersionSwitchModal({
6657
6995
  marginTop: 16
6658
6996
  },
6659
6997
  children: [
6660
- /* @__PURE__ */ jsx22(
6998
+ /* @__PURE__ */ jsx25(
6661
6999
  "button",
6662
7000
  {
6663
7001
  type: "button",
@@ -6675,7 +7013,7 @@ function VersionSwitchModal({
6675
7013
  children: "Cancel"
6676
7014
  }
6677
7015
  ),
6678
- /* @__PURE__ */ jsxs20(
7016
+ /* @__PURE__ */ jsxs23(
6679
7017
  "button",
6680
7018
  {
6681
7019
  type: "button",
@@ -6709,17 +7047,17 @@ function VersionSwitchModal({
6709
7047
  }
6710
7048
 
6711
7049
  // src/components/CommentNode.tsx
6712
- import { useRef as useRef12, useState as useState15 } from "react";
6713
- import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
7050
+ import { useRef as useRef14, useState as useState16 } from "react";
7051
+ import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
6714
7052
  function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6715
- const [editing, setEditing] = useState15(false);
6716
- const [draft, setDraft] = useState15(comment.text);
6717
- const textareaRef = useRef12(null);
7053
+ const [editing, setEditing] = useState16(false);
7054
+ const [draft, setDraft] = useState16(comment.text);
7055
+ const textareaRef = useRef14(null);
6718
7056
  const commitEdit = () => {
6719
7057
  setEditing(false);
6720
7058
  if (draft !== comment.text) onUpdate({ text: draft });
6721
7059
  };
6722
- return /* @__PURE__ */ jsxs21(
7060
+ return /* @__PURE__ */ jsxs24(
6723
7061
  "div",
6724
7062
  {
6725
7063
  "data-testid": `comment-${comment.id}`,
@@ -6740,8 +7078,8 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6740
7078
  userSelect: "none"
6741
7079
  },
6742
7080
  children: [
6743
- /* @__PURE__ */ jsxs21("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
6744
- !disabled && !editing && /* @__PURE__ */ jsx23(
7081
+ /* @__PURE__ */ jsxs24("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7082
+ !disabled && !editing && /* @__PURE__ */ jsx26(
6745
7083
  "button",
6746
7084
  {
6747
7085
  type: "button",
@@ -6756,7 +7094,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6756
7094
  children: "\u270F\uFE0F"
6757
7095
  }
6758
7096
  ),
6759
- !disabled && /* @__PURE__ */ jsx23(
7097
+ !disabled && /* @__PURE__ */ jsx26(
6760
7098
  "button",
6761
7099
  {
6762
7100
  type: "button",
@@ -6768,7 +7106,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6768
7106
  }
6769
7107
  )
6770
7108
  ] }),
6771
- editing ? /* @__PURE__ */ jsx23(
7109
+ editing ? /* @__PURE__ */ jsx26(
6772
7110
  "textarea",
6773
7111
  {
6774
7112
  ref: textareaRef,
@@ -6794,7 +7132,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6794
7132
  },
6795
7133
  "data-testid": `comment-textarea-${comment.id}`
6796
7134
  }
6797
- ) : /* @__PURE__ */ jsx23(
7135
+ ) : /* @__PURE__ */ jsx26(
6798
7136
  "div",
6799
7137
  {
6800
7138
  onDoubleClick: () => {
@@ -6804,7 +7142,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6804
7142
  }
6805
7143
  },
6806
7144
  style: { whiteSpace: "pre-wrap", wordBreak: "break-word", minHeight: 20 },
6807
- children: comment.text || /* @__PURE__ */ jsx23("em", { style: { color: "#94a3b8" }, children: "empty note" })
7145
+ children: comment.text || /* @__PURE__ */ jsx26("em", { style: { color: "#94a3b8" }, children: "empty note" })
6808
7146
  }
6809
7147
  )
6810
7148
  ]
@@ -6822,14 +7160,14 @@ var iconBtn = {
6822
7160
  };
6823
7161
 
6824
7162
  // src/components/WorkflowJsonEditor.tsx
6825
- import { useEffect as useEffect10, useMemo as useMemo6, useRef as useRef13, useState as useState16 } from "react";
7163
+ import { useEffect as useEffect12, useMemo as useMemo6, useRef as useRef15, useState as useState17 } from "react";
6826
7164
  import {
6827
7165
  attachCursorSelectionBridge,
6828
7166
  attachWorkflowJsonController,
6829
7167
  registerWorkflowSchema,
6830
7168
  revealIdInEditor
6831
7169
  } from "@cyoda/workflow-monaco";
6832
- import { Fragment as Fragment9, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
7170
+ import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
6833
7171
  function WorkflowJsonEditor({
6834
7172
  document: document2,
6835
7173
  issues,
@@ -6841,20 +7179,20 @@ function WorkflowJsonEditor({
6841
7179
  onSelectionChange,
6842
7180
  onStatusChange
6843
7181
  }) {
6844
- const containerRef = useRef13(null);
6845
- const documentRef = useRef13(document2);
6846
- const issuesRef = useRef13(issues);
6847
- const readOnlyRef = useRef13(readOnly);
6848
- const onPatchRef = useRef13(onPatch);
6849
- const onSelectionChangeRef = useRef13(onSelectionChange);
6850
- const onStatusChangeRef = useRef13(onStatusChange);
6851
- const editorRef = useRef13(null);
6852
- const controllerRef = useRef13(null);
6853
- const schemaHandleRef = useRef13(null);
6854
- const cursorBridgeRef = useRef13(null);
6855
- const applyingGraphSelectionRef = useRef13(false);
6856
- const visibleRef = useRef13(visible);
6857
- const [status, setStatus] = useState16({ status: "idle" });
7182
+ const containerRef = useRef15(null);
7183
+ const documentRef = useRef15(document2);
7184
+ const issuesRef = useRef15(issues);
7185
+ const readOnlyRef = useRef15(readOnly);
7186
+ const onPatchRef = useRef15(onPatch);
7187
+ const onSelectionChangeRef = useRef15(onSelectionChange);
7188
+ const onStatusChangeRef = useRef15(onStatusChange);
7189
+ const editorRef = useRef15(null);
7190
+ const controllerRef = useRef15(null);
7191
+ const schemaHandleRef = useRef15(null);
7192
+ const cursorBridgeRef = useRef15(null);
7193
+ const applyingGraphSelectionRef = useRef15(false);
7194
+ const visibleRef = useRef15(visible);
7195
+ const [status, setStatus] = useState17({ status: "idle" });
6858
7196
  documentRef.current = document2;
6859
7197
  issuesRef.current = issues;
6860
7198
  readOnlyRef.current = readOnly;
@@ -6870,7 +7208,7 @@ function WorkflowJsonEditor({
6870
7208
  const modelUri = config?.modelUri;
6871
7209
  const editorOptions = config?.editorOptions;
6872
7210
  const debounceMs = config?.debounceMs;
6873
- useEffect10(() => {
7211
+ useEffect12(() => {
6874
7212
  if (!monaco || !containerRef.current || editorRef.current) return;
6875
7213
  const model = monaco.editor.createModel(
6876
7214
  "",
@@ -6925,7 +7263,7 @@ function WorkflowJsonEditor({
6925
7263
  model.dispose();
6926
7264
  };
6927
7265
  }, [monaco, modelUri]);
6928
- useEffect10(() => {
7266
+ useEffect12(() => {
6929
7267
  const editor = editorRef.current;
6930
7268
  const controller = controllerRef.current;
6931
7269
  if (!editor || !controller || !config) return;
@@ -6933,17 +7271,17 @@ function WorkflowJsonEditor({
6933
7271
  controller.syncFromDocument(document2);
6934
7272
  controller.renderIssues(issues, document2);
6935
7273
  }, [config, document2, issues, readOnly]);
6936
- useEffect10(() => {
7274
+ useEffect12(() => {
6937
7275
  if (!visible) return;
6938
7276
  editorRef.current?.layout?.();
6939
7277
  }, [visible]);
6940
- useEffect10(() => {
7278
+ useEffect12(() => {
6941
7279
  if (!config) {
6942
7280
  setStatus({ status: "idle" });
6943
7281
  onStatusChangeRef.current?.({ status: "idle" });
6944
7282
  }
6945
7283
  }, [config]);
6946
- useEffect10(() => {
7284
+ useEffect12(() => {
6947
7285
  const editor = editorRef.current;
6948
7286
  if (!editor || !visible || !selectedId) return;
6949
7287
  applyingGraphSelectionRef.current = true;
@@ -6954,7 +7292,7 @@ function WorkflowJsonEditor({
6954
7292
  return () => window.clearTimeout(timeout);
6955
7293
  }, [document2, selectedId, visible]);
6956
7294
  if (!config) {
6957
- return /* @__PURE__ */ jsx24(
7295
+ return /* @__PURE__ */ jsx27(
6958
7296
  "div",
6959
7297
  {
6960
7298
  "data-testid": "workflow-json-unavailable",
@@ -6969,11 +7307,11 @@ function WorkflowJsonEditor({
6969
7307
  textAlign: "center",
6970
7308
  background: "#F8FAFC"
6971
7309
  },
6972
- children: /* @__PURE__ */ jsx24(UnavailableMessage, {})
7310
+ children: /* @__PURE__ */ jsx27(UnavailableMessage, {})
6973
7311
  }
6974
7312
  );
6975
7313
  }
6976
- return /* @__PURE__ */ jsxs22(
7314
+ return /* @__PURE__ */ jsxs25(
6977
7315
  "div",
6978
7316
  {
6979
7317
  "data-testid": "workflow-json-editor",
@@ -6985,8 +7323,8 @@ function WorkflowJsonEditor({
6985
7323
  minHeight: 0
6986
7324
  },
6987
7325
  children: [
6988
- /* @__PURE__ */ jsx24(JsonStatusBanner, { status }),
6989
- /* @__PURE__ */ jsx24(
7326
+ /* @__PURE__ */ jsx27(JsonStatusBanner, { status }),
7327
+ /* @__PURE__ */ jsx27(
6990
7328
  "div",
6991
7329
  {
6992
7330
  ref: containerRef,
@@ -6999,7 +7337,7 @@ function WorkflowJsonEditor({
6999
7337
  }
7000
7338
  function UnavailableMessage() {
7001
7339
  const messages = useMessages();
7002
- return /* @__PURE__ */ jsx24(Fragment9, { children: messages.editorView.unavailable });
7340
+ return /* @__PURE__ */ jsx27(Fragment10, { children: messages.editorView.unavailable });
7003
7341
  }
7004
7342
  function JsonStatusBanner({ status }) {
7005
7343
  const messages = useMessages();
@@ -7008,7 +7346,7 @@ function JsonStatusBanner({ status }) {
7008
7346
  }
7009
7347
  const tone = status.status === "semantic-errors" ? { border: "#FCD34D", bg: "#FFFBEB", text: "#92400E" } : { border: "#FCA5A5", bg: "#FEF2F2", text: "#991B1B" };
7010
7348
  const body = status.status === "semantic-errors" ? messages.editorView.semanticErrors : status.status === "invalid-schema" ? messages.editorView.invalidSchema : `${messages.editorView.invalidJson}${status.message ? ` ${status.message}` : ""}`;
7011
- return /* @__PURE__ */ jsx24(
7349
+ return /* @__PURE__ */ jsx27(
7012
7350
  "div",
7013
7351
  {
7014
7352
  role: "status",
@@ -7052,7 +7390,7 @@ function selectionFromJsonId(doc, id) {
7052
7390
  }
7053
7391
 
7054
7392
  // src/components/WorkflowEditor.tsx
7055
- import { Fragment as Fragment10, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
7393
+ import { Fragment as Fragment11, jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
7056
7394
  function hasPersistedWorkflowUi(meta) {
7057
7395
  return !!meta && Object.values(meta).some((value) => value !== void 0);
7058
7396
  }
@@ -7119,36 +7457,46 @@ function WorkflowEditor({
7119
7457
  }
7120
7458
  }, []);
7121
7459
  const [state, actions] = useEditorStore(initialDocumentWithLayout, mode);
7122
- const [isFullscreen, setIsFullscreen] = useState17(false);
7123
- const [inspectorWidth, setInspectorWidth] = useState17(384);
7124
- const editorContainerRef = useRef14(null);
7125
- const [pendingDelete, setPendingDelete] = useState17(null);
7126
- const [pendingConnect, setPendingConnect] = useState17(null);
7127
- const [pendingAddState, setPendingAddState] = useState17(null);
7128
- const [helpOpen, setHelpOpen] = useState17(false);
7129
- const [reconnectError, setReconnectError] = useState17(null);
7130
- const [layoutKey, setLayoutKey] = useState17(0);
7131
- const [activeSurface, setActiveSurface] = useState17("graph");
7132
- const [jsonStatus, setJsonStatus] = useState17({ status: "idle" });
7133
- const [openIssueSeverity, setOpenIssueSeverity] = useState17(null);
7134
- const [inspectorOpen, setInspectorOpen] = useState17(false);
7135
- const [pendingVersionSwitch, setPendingVersionSwitch] = useState17(null);
7136
- const selectionRef = useRef14(state.selection);
7137
- const documentStateRef = useRef14(state.document);
7138
- const activeWorkflowRef = useRef14(state.activeWorkflow);
7139
- const pendingSelectionRestoreRef = useRef14(null);
7140
- const newStatePositionRef = useRef14(null);
7141
- useEffect11(() => {
7460
+ const [isFullscreen, setIsFullscreen] = useState18(false);
7461
+ const [inspectorWidth, setInspectorWidth] = useState18(384);
7462
+ const editorContainerRef = useRef16(null);
7463
+ const [pendingDelete, setPendingDelete] = useState18(null);
7464
+ const [pendingConnect, setPendingConnect] = useState18(null);
7465
+ const [pendingAddState, setPendingAddState] = useState18(null);
7466
+ const [helpOpen, setHelpOpen] = useState18(false);
7467
+ const [reconnectError, setReconnectError] = useState18(null);
7468
+ const [layoutKey, setLayoutKey] = useState18(0);
7469
+ const [activeSurface, setActiveSurface] = useState18("graph");
7470
+ const [jsonStatus, setJsonStatus] = useState18({ status: "idle" });
7471
+ const [openIssueSeverity, setOpenIssueSeverity] = useState18(null);
7472
+ const [inspectorOpen, setInspectorOpen] = useState18(false);
7473
+ const [placement, setPlacement] = useState18(() => {
7474
+ const loaded = loadPlacement(localStorageKey);
7475
+ if (loaded) {
7476
+ return {
7477
+ ...loaded,
7478
+ rect: clampRect(loaded.rect, { w: window.innerWidth, h: window.innerHeight })
7479
+ };
7480
+ }
7481
+ return { mode: "docked", rect: { left: 120, top: 96, width: 460, height: 560 } };
7482
+ });
7483
+ const [pendingVersionSwitch, setPendingVersionSwitch] = useState18(null);
7484
+ const selectionRef = useRef16(state.selection);
7485
+ const documentStateRef = useRef16(state.document);
7486
+ const activeWorkflowRef = useRef16(state.activeWorkflow);
7487
+ const pendingSelectionRestoreRef = useRef16(null);
7488
+ const newStatePositionRef = useRef16(null);
7489
+ useEffect13(() => {
7142
7490
  selectionRef.current = state.selection;
7143
7491
  }, [state.selection]);
7144
- useEffect11(() => {
7492
+ useEffect13(() => {
7145
7493
  documentStateRef.current = state.document;
7146
7494
  activeWorkflowRef.current = state.activeWorkflow;
7147
7495
  }, [state.document, state.activeWorkflow]);
7148
- useEffect11(() => {
7496
+ useEffect13(() => {
7149
7497
  onChange?.(state.document);
7150
7498
  }, [state.document, onChange]);
7151
- useEffect11(() => {
7499
+ useEffect13(() => {
7152
7500
  try {
7153
7501
  const toStore = {};
7154
7502
  for (const [wfName, ui] of Object.entries(state.document.meta.workflowUi)) {
@@ -7167,26 +7515,38 @@ function WorkflowEditor({
7167
7515
  } catch {
7168
7516
  }
7169
7517
  }, [state.document.meta.workflowUi, localStorageKey, onWorkflowUiChange]);
7170
- useEffect11(() => {
7518
+ useEffect13(() => {
7171
7519
  if (!onLayoutMetadataChange || !state.activeWorkflow) return;
7172
7520
  const ui = state.document.meta.workflowUi[state.activeWorkflow];
7173
7521
  if (ui) onLayoutMetadataChange(ui);
7174
7522
  }, [state.document.meta.workflowUi, state.activeWorkflow, onLayoutMetadataChange]);
7175
- const handleInspectorResizeStart = useCallback3((e) => {
7176
- e.preventDefault();
7177
- const startX = e.clientX;
7178
- const startWidth = inspectorWidth;
7179
- const onMove = (ev) => {
7180
- const delta = startX - ev.clientX;
7181
- setInspectorWidth(Math.max(360, startWidth + delta));
7182
- };
7183
- const onUp = () => {
7184
- document.removeEventListener("mousemove", onMove);
7185
- document.removeEventListener("mouseup", onUp);
7186
- };
7187
- document.addEventListener("mousemove", onMove);
7188
- document.addEventListener("mouseup", onUp);
7189
- }, [inspectorWidth]);
7523
+ useEffect13(() => {
7524
+ savePlacement(localStorageKey, placement);
7525
+ }, [placement, localStorageKey]);
7526
+ const toggleDock = useCallback3(() => {
7527
+ setPlacement((p) => {
7528
+ const viewport = { w: window.innerWidth, h: window.innerHeight };
7529
+ if (p.mode === "docked") {
7530
+ return { mode: "floating", rect: clampRect(p.rect, viewport) };
7531
+ }
7532
+ return { ...p, mode: "docked" };
7533
+ });
7534
+ }, []);
7535
+ const minimizeInspector = useCallback3(() => {
7536
+ setPlacement(
7537
+ (p) => p.mode === "minimized" ? p : { mode: "minimized", rect: p.rect, restoreMode: p.mode }
7538
+ );
7539
+ }, []);
7540
+ const restoreInspector = useCallback3(() => {
7541
+ setPlacement((p) => {
7542
+ if (p.mode !== "minimized") return p;
7543
+ const back = p.restoreMode ?? "docked";
7544
+ if (back === "floating") {
7545
+ return { mode: "floating", rect: clampRect(p.rect, { w: window.innerWidth, h: window.innerHeight }) };
7546
+ }
7547
+ return { mode: "docked", rect: p.rect };
7548
+ });
7549
+ }, []);
7190
7550
  const handleToggleFullscreen = useCallback3(() => {
7191
7551
  setIsFullscreen((v) => !v);
7192
7552
  }, []);
@@ -7202,13 +7562,6 @@ function WorkflowEditor({
7202
7562
  kind: "transition",
7203
7563
  transitionUuid: patch.host.transitionUuid
7204
7564
  };
7205
- pendingSelectionRestoreRef.current = restoreSelection;
7206
- window.setTimeout(() => {
7207
- if (sameSelection(pendingSelectionRestoreRef.current, restoreSelection)) {
7208
- actions.setSelection(restoreSelection);
7209
- pendingSelectionRestoreRef.current = null;
7210
- }
7211
- }, 50);
7212
7565
  actions.dispatchTransaction({
7213
7566
  summary: patch.criterion ? "Set criterion" : "Clear criterion",
7214
7567
  patches: [patch],
@@ -7545,7 +7898,7 @@ function WorkflowEditor({
7545
7898
  },
7546
7899
  [anyModalOpen, readOnly, state.selection]
7547
7900
  );
7548
- useEffect11(() => {
7901
+ useEffect13(() => {
7549
7902
  const handleDocumentDeleteKeyDown = (event) => {
7550
7903
  if (anyModalOpen || readOnly || isTypingTarget(event.target)) return;
7551
7904
  if (event.ctrlKey || event.metaKey || event.altKey) return;
@@ -7582,7 +7935,7 @@ function WorkflowEditor({
7582
7935
  [layoutOptions, pinnedNodes]
7583
7936
  );
7584
7937
  const savedViewport = state.activeWorkflow ? state.document.meta.workflowUi[state.activeWorkflow]?.viewports?.[orientation] : void 0;
7585
- useEffect11(() => {
7938
+ useEffect13(() => {
7586
7939
  if (enableJsonEditor) return;
7587
7940
  setJsonStatus({ status: "idle" });
7588
7941
  onJsonStatusChange?.({ status: "idle" });
@@ -7621,13 +7974,13 @@ function WorkflowEditor({
7621
7974
  if (readOnly || anyModalOpen) return;
7622
7975
  openAddStateModal({ x, y });
7623
7976
  }, [anyModalOpen, openAddStateModal, readOnly]);
7624
- const graphPane = /* @__PURE__ */ jsxs23(
7977
+ const graphPane = /* @__PURE__ */ jsxs26(
7625
7978
  "div",
7626
7979
  {
7627
7980
  "data-testid": "workflow-editor-graph-pane",
7628
7981
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%", position: "relative" },
7629
7982
  children: [
7630
- /* @__PURE__ */ jsx25(
7983
+ /* @__PURE__ */ jsx28(
7631
7984
  Canvas,
7632
7985
  {
7633
7986
  graph: derived.graph,
@@ -7672,7 +8025,7 @@ function WorkflowEditor({
7672
8025
  helpLabel: mergedMessages.toolbar.help
7673
8026
  }
7674
8027
  ),
7675
- reconnectError && /* @__PURE__ */ jsx25(
8028
+ reconnectError && /* @__PURE__ */ jsx28(
7676
8029
  "div",
7677
8030
  {
7678
8031
  role: "alert",
@@ -7697,7 +8050,7 @@ function WorkflowEditor({
7697
8050
  state.activeWorkflow && (() => {
7698
8051
  const comments = state.document.meta.workflowUi[state.activeWorkflow]?.comments;
7699
8052
  if (!comments) return null;
7700
- return Object.values(comments).map((c) => /* @__PURE__ */ jsx25(
8053
+ return Object.values(comments).map((c) => /* @__PURE__ */ jsx28(
7701
8054
  CommentNode,
7702
8055
  {
7703
8056
  comment: c,
@@ -7720,12 +8073,12 @@ function WorkflowEditor({
7720
8073
  ]
7721
8074
  }
7722
8075
  );
7723
- const jsonPane = enableJsonEditor ? /* @__PURE__ */ jsx25(
8076
+ const jsonPane = enableJsonEditor ? /* @__PURE__ */ jsx28(
7724
8077
  "div",
7725
8078
  {
7726
8079
  "data-testid": "workflow-editor-json-pane",
7727
8080
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%" },
7728
- children: /* @__PURE__ */ jsx25(
8081
+ children: /* @__PURE__ */ jsx28(
7729
8082
  WorkflowJsonEditor,
7730
8083
  {
7731
8084
  document: state.document,
@@ -7741,7 +8094,7 @@ function WorkflowEditor({
7741
8094
  )
7742
8095
  }
7743
8096
  ) : null;
7744
- return /* @__PURE__ */ jsx25(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ jsx25(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ jsx25(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ jsxs23(
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(
7745
8098
  "div",
7746
8099
  {
7747
8100
  ref: editorContainerRef,
@@ -7762,7 +8115,7 @@ function WorkflowEditor({
7762
8115
  onKeyDown: handleKeyDown,
7763
8116
  tabIndex: -1,
7764
8117
  children: [
7765
- chrome?.tabs !== false && showTabs && /* @__PURE__ */ jsx25(
8118
+ chrome?.tabs !== false && showTabs && /* @__PURE__ */ jsx28(
7766
8119
  WorkflowTabs,
7767
8120
  {
7768
8121
  workflows,
@@ -7789,9 +8142,9 @@ function WorkflowEditor({
7789
8142
  onVersionChange: handleVersionChange
7790
8143
  }
7791
8144
  ),
7792
- /* @__PURE__ */ jsxs23("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
7793
- /* @__PURE__ */ jsxs23("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
7794
- (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ jsxs23(
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(
7795
8148
  "div",
7796
8149
  {
7797
8150
  style: {
@@ -7805,8 +8158,8 @@ function WorkflowEditor({
7805
8158
  },
7806
8159
  "data-testid": "workflow-editor-surface-tabs",
7807
8160
  children: [
7808
- enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ jsxs23(Fragment10, { children: [
7809
- /* @__PURE__ */ jsx25(
8161
+ enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ jsxs26(Fragment11, { children: [
8162
+ /* @__PURE__ */ jsx28(
7810
8163
  SurfaceTab,
7811
8164
  {
7812
8165
  active: activeSurface === "graph",
@@ -7814,7 +8167,7 @@ function WorkflowEditor({
7814
8167
  children: mergedMessages.editorView.graph
7815
8168
  }
7816
8169
  ),
7817
- /* @__PURE__ */ jsx25(
8170
+ /* @__PURE__ */ jsx28(
7818
8171
  SurfaceTab,
7819
8172
  {
7820
8173
  active: activeSurface === "json",
@@ -7823,8 +8176,8 @@ function WorkflowEditor({
7823
8176
  }
7824
8177
  )
7825
8178
  ] }),
7826
- /* @__PURE__ */ jsx25("div", { style: { flex: 1 } }),
7827
- !readOnly && activeSurface === "graph" && /* @__PURE__ */ jsxs23(
8179
+ /* @__PURE__ */ jsx28("div", { style: { flex: 1 } }),
8180
+ !readOnly && activeSurface === "graph" && /* @__PURE__ */ jsxs26(
7828
8181
  "button",
7829
8182
  {
7830
8183
  type: "button",
@@ -7845,7 +8198,7 @@ function WorkflowEditor({
7845
8198
  cursor: "pointer"
7846
8199
  },
7847
8200
  children: [
7848
- /* @__PURE__ */ jsx25("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ jsx25("path", { d: "M12 5v14M5 12h14" }) }),
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" }) }),
7849
8202
  mergedMessages.toolbar.addStateButton
7850
8203
  ]
7851
8204
  }
@@ -7853,7 +8206,7 @@ function WorkflowEditor({
7853
8206
  ]
7854
8207
  }
7855
8208
  ),
7856
- enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ jsxs23(
8209
+ enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ jsxs26(
7857
8210
  "div",
7858
8211
  {
7859
8212
  style: {
@@ -7866,10 +8219,10 @@ function WorkflowEditor({
7866
8219
  "data-testid": "workflow-editor-split-view",
7867
8220
  children: [
7868
8221
  graphPane,
7869
- /* @__PURE__ */ jsx25("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8222
+ /* @__PURE__ */ jsx28("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
7870
8223
  ]
7871
8224
  }
7872
- ) : /* @__PURE__ */ jsxs23(
8225
+ ) : /* @__PURE__ */ jsxs26(
7873
8226
  "div",
7874
8227
  {
7875
8228
  style: {
@@ -7881,8 +8234,8 @@ function WorkflowEditor({
7881
8234
  flexDirection: "column"
7882
8235
  },
7883
8236
  children: [
7884
- graphVisible ? /* @__PURE__ */ jsx25("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
7885
- enableJsonEditor ? /* @__PURE__ */ jsx25(
8237
+ graphVisible ? /* @__PURE__ */ jsx28("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8238
+ enableJsonEditor ? /* @__PURE__ */ jsx28(
7886
8239
  "div",
7887
8240
  {
7888
8241
  style: {
@@ -7899,41 +8252,36 @@ function WorkflowEditor({
7899
8252
  }
7900
8253
  )
7901
8254
  ] }),
7902
- inspectorVisible && /* @__PURE__ */ jsxs23(Fragment10, { children: [
7903
- /* @__PURE__ */ jsx25(
7904
- "div",
7905
- {
7906
- onMouseDown: handleInspectorResizeStart,
7907
- style: {
7908
- width: 3,
7909
- flexShrink: 0,
7910
- cursor: "col-resize",
7911
- background: "transparent",
7912
- borderLeft: "1px solid #E2E8F0",
7913
- transition: "background 0.15s",
7914
- zIndex: 10
7915
- },
7916
- onMouseEnter: (e) => e.currentTarget.style.background = "#CBD5E1",
7917
- onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
7918
- }
7919
- ),
7920
- /* @__PURE__ */ jsx25(
7921
- Inspector,
7922
- {
7923
- document: state.document,
7924
- selection: state.selection,
7925
- issues: derived.issues,
7926
- readOnly,
7927
- onDispatch: dispatch,
7928
- onSelectionChange: handleSelectionChange,
7929
- onClose: () => handleSelectionChange(null),
7930
- onRequestDeleteState: requestDeleteState,
7931
- width: inspectorWidth
7932
- }
7933
- )
7934
- ] })
8255
+ inspectorVisible && /* @__PURE__ */ jsx28(
8256
+ InspectorFrame,
8257
+ {
8258
+ mode: placement.mode,
8259
+ rect: placement.rect,
8260
+ dockedWidth: inspectorWidth,
8261
+ onRectChange: (rect) => setPlacement((p) => ({ ...p, rect })),
8262
+ onDockedWidthChange: setInspectorWidth,
8263
+ onRestore: restoreInspector,
8264
+ onClose: () => handleSelectionChange(null),
8265
+ children: /* @__PURE__ */ jsx28(
8266
+ Inspector,
8267
+ {
8268
+ document: state.document,
8269
+ selection: state.selection,
8270
+ issues: derived.issues,
8271
+ readOnly,
8272
+ onDispatch: dispatch,
8273
+ onSelectionChange: handleSelectionChange,
8274
+ onClose: () => handleSelectionChange(null),
8275
+ onRequestDeleteState: requestDeleteState,
8276
+ docked: placement.mode === "docked",
8277
+ onToggleDock: toggleDock,
8278
+ onMinimize: minimizeInspector
8279
+ }
8280
+ )
8281
+ }
8282
+ )
7935
8283
  ] }),
7936
- pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ jsx25(
8284
+ pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ jsx28(
7937
8285
  AddStateModal,
7938
8286
  {
7939
8287
  existingNames: Object.keys(
@@ -7945,7 +8293,7 @@ function WorkflowEditor({
7945
8293
  onCancel: () => setPendingAddState(null)
7946
8294
  }
7947
8295
  ),
7948
- pendingDelete && /* @__PURE__ */ jsx25(
8296
+ pendingDelete && /* @__PURE__ */ jsx28(
7949
8297
  DeleteStateModal,
7950
8298
  {
7951
8299
  document: state.document,
@@ -7955,7 +8303,7 @@ function WorkflowEditor({
7955
8303
  onCancel: () => setPendingDelete(null)
7956
8304
  }
7957
8305
  ),
7958
- pendingConnect && pendingConnectState && /* @__PURE__ */ jsx25(
8306
+ pendingConnect && pendingConnectState && /* @__PURE__ */ jsx28(
7959
8307
  DragConnectModal,
7960
8308
  {
7961
8309
  source: pendingConnectState,
@@ -7965,8 +8313,8 @@ function WorkflowEditor({
7965
8313
  onCancel: () => setPendingConnect(null)
7966
8314
  }
7967
8315
  ),
7968
- helpOpen && /* @__PURE__ */ jsx25(HelpModal, { onCancel: () => setHelpOpen(false) }),
7969
- pendingVersionSwitch && /* @__PURE__ */ jsx25(
8316
+ helpOpen && /* @__PURE__ */ jsx28(HelpModal, { onCancel: () => setHelpOpen(false) }),
8317
+ pendingVersionSwitch && /* @__PURE__ */ jsx28(
7970
8318
  VersionSwitchModal,
7971
8319
  {
7972
8320
  fromVersion: `v${state.document.meta.cyodaVersion ?? LATEST_CYODA_VERSION}`,
@@ -7979,8 +8327,8 @@ function WorkflowEditor({
7979
8327
  onCancel: () => setPendingVersionSwitch(null)
7980
8328
  }
7981
8329
  ),
7982
- chrome?.toolbar !== false && /* @__PURE__ */ jsxs23("div", { style: { position: "relative" }, children: [
7983
- /* @__PURE__ */ jsx25(
8330
+ chrome?.toolbar !== false && /* @__PURE__ */ jsxs26("div", { style: { position: "relative" }, children: [
8331
+ /* @__PURE__ */ jsx28(
7984
8332
  Toolbar,
7985
8333
  {
7986
8334
  derived,
@@ -7995,7 +8343,7 @@ function WorkflowEditor({
7995
8343
  toolbarEnd
7996
8344
  }
7997
8345
  ),
7998
- /* @__PURE__ */ jsx25(
8346
+ /* @__PURE__ */ jsx28(
7999
8347
  IssuesDrawer,
8000
8348
  {
8001
8349
  open: openIssueSeverity !== null,
@@ -8153,22 +8501,6 @@ function normalizeAnchorPair(anchors) {
8153
8501
  function sameAnchors(a, b) {
8154
8502
  return a?.source === b?.source && a?.target === b?.target;
8155
8503
  }
8156
- function sameSelection(a, b) {
8157
- if (a === b) return true;
8158
- if (!a || !b || a.kind !== b.kind) return false;
8159
- switch (a.kind) {
8160
- case "workflow":
8161
- return b.kind === "workflow" && a.workflow === b.workflow;
8162
- case "state":
8163
- return b.kind === "state" && a.workflow === b.workflow && a.stateCode === b.stateCode && a.nodeId === b.nodeId;
8164
- case "transition":
8165
- return b.kind === "transition" && a.transitionUuid === b.transitionUuid;
8166
- case "processor":
8167
- return b.kind === "processor" && a.processorUuid === b.processorUuid;
8168
- case "criterion":
8169
- return b.kind === "criterion" && a.hostKind === b.hostKind && a.hostId === b.hostId && a.path.length === b.path.length && a.path.every((part, index) => part === b.path[index]);
8170
- }
8171
- }
8172
8504
  function workflowForSelection(doc, selection) {
8173
8505
  if (!selection) return null;
8174
8506
  if (selection.kind === "workflow" || selection.kind === "state") return selection.workflow;
@@ -8191,7 +8523,7 @@ function SurfaceTab({
8191
8523
  onClick,
8192
8524
  children
8193
8525
  }) {
8194
- return /* @__PURE__ */ jsx25(
8526
+ return /* @__PURE__ */ jsx28(
8195
8527
  "button",
8196
8528
  {
8197
8529
  type: "button",
@@ -8246,18 +8578,18 @@ function snapToGrid(value, grid = 16) {
8246
8578
  }
8247
8579
 
8248
8580
  // src/save/useSaveFlow.ts
8249
- import { useCallback as useCallback4, useRef as useRef15, useState as useState18 } from "react";
8581
+ import { useCallback as useCallback4, useRef as useRef17, useState as useState19 } from "react";
8250
8582
  import {
8251
8583
  WorkflowApiConflictError
8252
8584
  } from "@cyoda/workflow-core";
8253
8585
  function useSaveFlow(args) {
8254
8586
  const { api, document: doc, concurrencyToken, onSaved, onReload } = args;
8255
- const [status, setStatus] = useState18({ kind: "idle" });
8256
- const tokenRef = useRef15(concurrencyToken);
8587
+ const [status, setStatus] = useState19({ kind: "idle" });
8588
+ const tokenRef = useRef17(concurrencyToken);
8257
8589
  tokenRef.current = concurrencyToken;
8258
- const entityRef = useRef15(doc.session.entity);
8590
+ const entityRef = useRef17(doc.session.entity);
8259
8591
  entityRef.current = doc.session.entity;
8260
- const payloadRef = useRef15({
8592
+ const payloadRef = useRef17({
8261
8593
  importMode: doc.session.importMode,
8262
8594
  workflows: doc.session.workflows
8263
8595
  });
@@ -8265,7 +8597,7 @@ function useSaveFlow(args) {
8265
8597
  importMode: doc.session.importMode,
8266
8598
  workflows: doc.session.workflows
8267
8599
  };
8268
- const savingRef = useRef15(false);
8600
+ const savingRef = useRef17(false);
8269
8601
  const performImport = useCallback4(
8270
8602
  async (token) => {
8271
8603
  if (savingRef.current) return;
@@ -8323,8 +8655,8 @@ function useSaveFlow(args) {
8323
8655
  }
8324
8656
 
8325
8657
  // src/save/SaveConfirmModal.tsx
8326
- import { useState as useState19 } from "react";
8327
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
8658
+ import { useState as useState20 } from "react";
8659
+ import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
8328
8660
  function SaveConfirmModal({
8329
8661
  mode,
8330
8662
  requiresExplicitConfirm,
@@ -8334,17 +8666,17 @@ function SaveConfirmModal({
8334
8666
  onCancel
8335
8667
  }) {
8336
8668
  const messages = useMessages();
8337
- const [ackMode, setAckMode] = useState19(!requiresExplicitConfirm);
8338
- const [ackWarnings, setAckWarnings] = useState19(warningCount === 0);
8669
+ const [ackMode, setAckMode] = useState20(!requiresExplicitConfirm);
8670
+ const [ackWarnings, setAckWarnings] = useState20(warningCount === 0);
8339
8671
  const blocked = !ackMode || !ackWarnings;
8340
- return /* @__PURE__ */ jsxs24(ModalFrame, { onCancel, children: [
8341
- /* @__PURE__ */ jsx26("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
8342
- /* @__PURE__ */ jsxs24("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
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: [
8343
8675
  messages.saveConfirm.modeLabel,
8344
8676
  ": ",
8345
- /* @__PURE__ */ jsx26("strong", { children: mode })
8677
+ /* @__PURE__ */ jsx29("strong", { children: mode })
8346
8678
  ] }),
8347
- diffSummary2 && /* @__PURE__ */ jsx26(
8679
+ diffSummary2 && /* @__PURE__ */ jsx29(
8348
8680
  "pre",
8349
8681
  {
8350
8682
  style: {
@@ -8363,8 +8695,8 @@ function SaveConfirmModal({
8363
8695
  children: diffSummary2
8364
8696
  }
8365
8697
  ),
8366
- requiresExplicitConfirm && /* @__PURE__ */ jsxs24("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8367
- /* @__PURE__ */ jsx26(
8698
+ requiresExplicitConfirm && /* @__PURE__ */ jsxs27("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8699
+ /* @__PURE__ */ jsx29(
8368
8700
  "input",
8369
8701
  {
8370
8702
  type: "checkbox",
@@ -8372,10 +8704,10 @@ function SaveConfirmModal({
8372
8704
  onChange: (e) => setAckMode(e.target.checked)
8373
8705
  }
8374
8706
  ),
8375
- /* @__PURE__ */ jsx26("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8707
+ /* @__PURE__ */ jsx29("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8376
8708
  ] }),
8377
- warningCount > 0 && /* @__PURE__ */ jsxs24("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8378
- /* @__PURE__ */ jsx26(
8709
+ warningCount > 0 && /* @__PURE__ */ jsxs27("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8710
+ /* @__PURE__ */ jsx29(
8379
8711
  "input",
8380
8712
  {
8381
8713
  type: "checkbox",
@@ -8383,11 +8715,11 @@ function SaveConfirmModal({
8383
8715
  onChange: (e) => setAckWarnings(e.target.checked)
8384
8716
  }
8385
8717
  ),
8386
- /* @__PURE__ */ jsx26("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8718
+ /* @__PURE__ */ jsx29("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8387
8719
  ] }),
8388
- /* @__PURE__ */ jsxs24("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
8389
- /* @__PURE__ */ jsx26("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
8390
- /* @__PURE__ */ jsx26(
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(
8391
8723
  "button",
8392
8724
  {
8393
8725
  type: "button",
@@ -8425,10 +8757,10 @@ var primaryBtn5 = {
8425
8757
  };
8426
8758
 
8427
8759
  // src/save/ConflictBanner.tsx
8428
- import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
8760
+ import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
8429
8761
  function ConflictBanner({ onReload, onForceOverwrite }) {
8430
8762
  const messages = useMessages();
8431
- return /* @__PURE__ */ jsxs25(
8763
+ return /* @__PURE__ */ jsxs28(
8432
8764
  "div",
8433
8765
  {
8434
8766
  style: {
@@ -8444,8 +8776,8 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8444
8776
  role: "alert",
8445
8777
  "data-testid": "conflict-banner",
8446
8778
  children: [
8447
- /* @__PURE__ */ jsx27("span", { style: { flex: 1 }, children: messages.conflict.message }),
8448
- /* @__PURE__ */ jsx27(
8779
+ /* @__PURE__ */ jsx30("span", { style: { flex: 1 }, children: messages.conflict.message }),
8780
+ /* @__PURE__ */ jsx30(
8449
8781
  "button",
8450
8782
  {
8451
8783
  type: "button",
@@ -8455,7 +8787,7 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8455
8787
  children: messages.conflict.reload
8456
8788
  }
8457
8789
  ),
8458
- /* @__PURE__ */ jsx27(
8790
+ /* @__PURE__ */ jsx30(
8459
8791
  "button",
8460
8792
  {
8461
8793
  type: "button",