@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.cjs CHANGED
@@ -33,8 +33,8 @@ __export(index_exports, {
33
33
  module.exports = __toCommonJS(index_exports);
34
34
 
35
35
  // src/components/WorkflowEditor.tsx
36
- var import_react23 = require("react");
37
- var import_workflow_core10 = require("@cyoda/workflow-core");
36
+ var import_react24 = require("react");
37
+ var import_workflow_core11 = require("@cyoda/workflow-core");
38
38
  var import_workflow_layout2 = require("@cyoda/workflow-layout");
39
39
 
40
40
  // src/i18n/context.ts
@@ -122,6 +122,13 @@ var defaultMessages = {
122
122
  processes: "Processes",
123
123
  criterion: "Criterion",
124
124
  criteria: "Criteria",
125
+ annotations: "Annotations",
126
+ annotationsAdd: "Add annotations",
127
+ annotationsApply: "Apply",
128
+ annotationsRevert: "Revert",
129
+ annotationsRemove: "Remove",
130
+ annotationsDocChanged: "Document changed underneath \u2014 Revert to reload.",
131
+ format: "Format",
125
132
  executionMode: "Execution mode",
126
133
  addProcessor: "Add processor",
127
134
  removeProcessor: "Remove",
@@ -143,7 +150,12 @@ var defaultMessages = {
143
150
  anchorBottomRight: "Bottom right",
144
151
  anchorLeftTop: "Left top",
145
152
  anchorLeft: "Left",
146
- anchorLeftBottom: "Left bottom"
153
+ anchorLeftBottom: "Left bottom",
154
+ detachPanel: "Detach panel",
155
+ dockPanel: "Dock panel",
156
+ minimize: "Minimize",
157
+ restore: "Restore",
158
+ minimizedTitle: "Inspector"
147
159
  },
148
160
  confirmDelete: {
149
161
  title: "Delete state?",
@@ -197,7 +209,9 @@ var defaultMessages = {
197
209
  noneAutomated: "No criterion. This automated transition will fire as soon as the entity reaches this state.",
198
210
  noneAutomatedWarning: "Automated transitions without criteria should usually be last in the transition order.",
199
211
  cancel: "Cancel",
200
- applyModal: "Apply"
212
+ applyModal: "Apply",
213
+ revert: "Revert",
214
+ collapse: "Collapse"
201
215
  }
202
216
  };
203
217
 
@@ -265,6 +279,8 @@ function summarize(patch) {
265
279
  return `Reorder processor`;
266
280
  case "setCriterion":
267
281
  return patch.criterion ? `Set criterion` : `Clear criterion`;
282
+ case "setAnnotations":
283
+ return patch.annotations ? `Set annotations` : `Clear annotations`;
268
284
  case "setImportMode":
269
285
  return `Set import mode to "${patch.mode}"`;
270
286
  case "setEntity":
@@ -2718,7 +2734,17 @@ function CanvasInner({
2718
2734
  onHelp && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2719
2735
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2720
2736
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CtrlBtn, { onClick: onHelp, title: helpLabel ?? "Help", testId: "canvas-help", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HelpIcon, {}) })
2721
- ] })
2737
+ ] }),
2738
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: "#E2E8F0" } }),
2739
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2740
+ CtrlBtn,
2741
+ {
2742
+ onClick: () => onSelectionChange(activeWorkflow ? { kind: "workflow", workflow: activeWorkflow } : null),
2743
+ title: "Workflow settings",
2744
+ testId: "canvas-workflow-settings",
2745
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkflowSettingsIcon, {})
2746
+ }
2747
+ )
2722
2748
  ]
2723
2749
  }
2724
2750
  ),
@@ -2838,6 +2864,16 @@ function HelpIcon() {
2838
2864
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
2839
2865
  ] });
2840
2866
  }
2867
+ function WorkflowSettingsIcon() {
2868
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2869
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "6", x2: "20", y2: "6" }),
2870
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "12", x2: "20", y2: "12" }),
2871
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "4", y1: "18", x2: "20", y2: "18" }),
2872
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "9", cy: "6", r: "2", fill: "white" }),
2873
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "15", cy: "12", r: "2", fill: "white" }),
2874
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "8", cy: "18", r: "2", fill: "white" })
2875
+ ] });
2876
+ }
2841
2877
  function Canvas(props) {
2842
2878
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_reactflow4.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CanvasInner, { ...props }) });
2843
2879
  }
@@ -2858,8 +2894,8 @@ function resolveConnection(doc, connection) {
2858
2894
  }
2859
2895
 
2860
2896
  // src/inspector/Inspector.tsx
2861
- var import_react15 = require("react");
2862
- var import_workflow_core7 = require("@cyoda/workflow-core");
2897
+ var import_react16 = require("react");
2898
+ var import_workflow_core8 = require("@cyoda/workflow-core");
2863
2899
 
2864
2900
  // src/style/tokens.ts
2865
2901
  var colors = {
@@ -3323,16 +3359,301 @@ var smallSelectStyle = {
3323
3359
  userSelect: "none"
3324
3360
  };
3325
3361
 
3326
- // src/inspector/WorkflowForm.tsx
3362
+ // src/inspector/AnnotationsField.tsx
3363
+ var import_react10 = require("react");
3364
+
3365
+ // src/inspector/JsonMonacoField.tsx
3366
+ var import_react9 = require("react");
3367
+
3368
+ // src/inspector/CriterionMonacoContext.tsx
3369
+ var import_react8 = require("react");
3370
+ var CriterionMonacoContext = (0, import_react8.createContext)(null);
3371
+ var CriterionMonacoProvider = CriterionMonacoContext.Provider;
3372
+ function useCriterionMonaco() {
3373
+ return (0, import_react8.useContext)(CriterionMonacoContext);
3374
+ }
3375
+
3376
+ // src/components/monacoDisposal.ts
3377
+ var installed = false;
3378
+ function isMonacoCanceled(reason) {
3379
+ if (reason == null || typeof reason !== "object") return false;
3380
+ return reason.name === "Canceled";
3381
+ }
3382
+ function installMonacoCancellationFilter() {
3383
+ if (installed || typeof window === "undefined") return;
3384
+ installed = true;
3385
+ window.addEventListener("unhandledrejection", (e) => {
3386
+ if (isMonacoCanceled(e.reason)) e.preventDefault();
3387
+ });
3388
+ }
3389
+ installMonacoCancellationFilter();
3390
+
3391
+ // src/inspector/JsonMonacoField.tsx
3327
3392
  var import_jsx_runtime7 = require("react/jsx-runtime");
3393
+ function reformat(text) {
3394
+ try {
3395
+ return JSON.stringify(JSON.parse(text), null, 2);
3396
+ } catch {
3397
+ return null;
3398
+ }
3399
+ }
3400
+ function JsonMonacoField(props) {
3401
+ const monaco = useCriterionMonaco();
3402
+ const messages = useMessages();
3403
+ const onFormat = () => {
3404
+ const next = reformat(props.buffer);
3405
+ if (next !== null && next !== props.buffer) props.onChange(next);
3406
+ };
3407
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
3408
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3409
+ "button",
3410
+ {
3411
+ type: "button",
3412
+ onClick: onFormat,
3413
+ disabled: props.disabled,
3414
+ "data-testid": `${props.testId}-format`,
3415
+ style: { ...ghostBtnStyle, fontSize: 11, padding: "2px 8px" },
3416
+ children: messages.inspector.format
3417
+ }
3418
+ ) }),
3419
+ monaco ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MonacoPane, { ...props, monaco }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3420
+ "textarea",
3421
+ {
3422
+ value: props.buffer,
3423
+ disabled: props.disabled,
3424
+ rows: 12,
3425
+ "data-testid": props.testId,
3426
+ onChange: (e) => props.onChange(e.target.value),
3427
+ style: {
3428
+ fontFamily: fonts.mono,
3429
+ fontSize: 12,
3430
+ padding: 8,
3431
+ whiteSpace: "pre-wrap",
3432
+ wordBreak: "break-word",
3433
+ border: `1px solid ${colors.border}`,
3434
+ borderRadius: radii.sm,
3435
+ background: colors.surface,
3436
+ resize: "vertical",
3437
+ minHeight: props.minHeightPx ?? 120
3438
+ }
3439
+ }
3440
+ )
3441
+ ] });
3442
+ }
3443
+ function MonacoPane({
3444
+ monaco,
3445
+ buffer,
3446
+ disabled,
3447
+ modelUri,
3448
+ onChange,
3449
+ seed,
3450
+ registerSchema,
3451
+ minHeightPx = 120,
3452
+ maxHeightPx = 480,
3453
+ testId
3454
+ }) {
3455
+ const containerRef = (0, import_react9.useRef)(null);
3456
+ const editorRef = (0, import_react9.useRef)(null);
3457
+ const modelRef = (0, import_react9.useRef)(null);
3458
+ (0, import_react9.useEffect)(() => {
3459
+ if (!containerRef.current || editorRef.current) return;
3460
+ const model = monaco.editor.createModel(buffer, "json", monaco.Uri.parse(modelUri));
3461
+ modelRef.current = model;
3462
+ const editor = monaco.editor.create(containerRef.current, {
3463
+ model,
3464
+ automaticLayout: true,
3465
+ minimap: { enabled: false },
3466
+ wordWrap: "on",
3467
+ fontSize: 13,
3468
+ tabSize: 2,
3469
+ scrollBeyondLastLine: false,
3470
+ theme: "vs",
3471
+ readOnly: disabled
3472
+ });
3473
+ editorRef.current = editor;
3474
+ installMonacoCancellationFilter();
3475
+ const schemaHandle = registerSchema?.(monaco) ?? null;
3476
+ const applyHeight = () => {
3477
+ const h = Math.min(Math.max(editor.getContentHeight?.() ?? minHeightPx, minHeightPx), maxHeightPx);
3478
+ if (containerRef.current) containerRef.current.style.height = `${h}px`;
3479
+ editor.layout?.();
3480
+ };
3481
+ applyHeight();
3482
+ const sizeSub = editor.onDidContentSizeChange?.(applyHeight) ?? { dispose() {
3483
+ } };
3484
+ const sub = model.onDidChangeContent(() => onChange(model.getValue()));
3485
+ return () => {
3486
+ sub.dispose();
3487
+ sizeSub.dispose();
3488
+ schemaHandle?.dispose();
3489
+ editor.dispose();
3490
+ editorRef.current = null;
3491
+ model.dispose();
3492
+ modelRef.current = null;
3493
+ };
3494
+ }, [monaco, modelUri]);
3495
+ (0, import_react9.useEffect)(() => {
3496
+ const model = modelRef.current;
3497
+ if (model && seed !== void 0 && model.getValue() !== seed) model.setValue(seed);
3498
+ }, [seed]);
3499
+ (0, import_react9.useEffect)(() => {
3500
+ editorRef.current?.updateOptions?.({ readOnly: disabled });
3501
+ }, [disabled]);
3502
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3503
+ "div",
3504
+ {
3505
+ ref: containerRef,
3506
+ "data-testid": testId,
3507
+ style: { height: minHeightPx, border: `1px solid ${colors.border}`, borderRadius: radii.sm }
3508
+ }
3509
+ );
3510
+ }
3511
+
3512
+ // src/inspector/annotationsJson.ts
3513
+ var import_workflow_core3 = require("@cyoda/workflow-core");
3514
+ function annotationsModelUri(key) {
3515
+ return `cyoda://annotations/${key}.json`;
3516
+ }
3517
+ function annotationBytes(value) {
3518
+ return new TextEncoder().encode(JSON.stringify(value)).length;
3519
+ }
3520
+ function sameJson(a, b) {
3521
+ return JSON.stringify(a) === JSON.stringify(b);
3522
+ }
3523
+ function parseAnnotationsJson(text) {
3524
+ let raw;
3525
+ try {
3526
+ raw = JSON.parse(text);
3527
+ } catch {
3528
+ return { annotations: null, error: "Invalid JSON." };
3529
+ }
3530
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
3531
+ return { annotations: null, error: "Annotations must be a JSON object." };
3532
+ }
3533
+ const bytes = annotationBytes(raw);
3534
+ if (bytes > import_workflow_core3.ANNOTATIONS_MAX_BYTES) {
3535
+ return {
3536
+ annotations: null,
3537
+ error: `Annotations are ${bytes} bytes, over the ${import_workflow_core3.ANNOTATIONS_MAX_BYTES}-byte limit.`
3538
+ };
3539
+ }
3540
+ return { annotations: raw, error: null };
3541
+ }
3542
+
3543
+ // src/inspector/AnnotationsField.tsx
3544
+ var import_jsx_runtime8 = require("react/jsx-runtime");
3545
+ var pretty = (v) => JSON.stringify(v, null, 2);
3546
+ function AnnotationsField(props) {
3547
+ const messages = useMessages();
3548
+ if (props.value === void 0) {
3549
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: sectionStyle, children: [
3550
+ props.showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SectionLabel, {}),
3551
+ !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3552
+ "button",
3553
+ {
3554
+ type: "button",
3555
+ style: primaryBtn,
3556
+ "data-testid": "inspector-annotations-add",
3557
+ onClick: () => props.onCommit({}),
3558
+ children: messages.inspector.annotationsAdd
3559
+ }
3560
+ )
3561
+ ] });
3562
+ }
3563
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AnnotationsEditor, { ...props, value: props.value }, props.modelKey);
3564
+ }
3565
+ function AnnotationsEditor({
3566
+ value,
3567
+ disabled,
3568
+ modelKey,
3569
+ onCommit,
3570
+ onRemove,
3571
+ showLabel
3572
+ }) {
3573
+ const messages = useMessages();
3574
+ const [buffer, setBuffer] = (0, import_react10.useState)(() => pretty(value));
3575
+ const [docChanged, setDocChanged] = (0, import_react10.useState)(false);
3576
+ const prevValueRef = (0, import_react10.useRef)(value);
3577
+ (0, import_react10.useEffect)(() => {
3578
+ if (sameJson(prevValueRef.current, value)) return;
3579
+ const parsed = parseAnnotationsJson(buffer).annotations;
3580
+ if (parsed !== null && sameJson(parsed, value)) {
3581
+ setDocChanged(false);
3582
+ } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3583
+ setBuffer(pretty(value));
3584
+ setDocChanged(false);
3585
+ } else {
3586
+ setDocChanged(true);
3587
+ }
3588
+ prevValueRef.current = value;
3589
+ }, [value, buffer]);
3590
+ const result = parseAnnotationsJson(buffer);
3591
+ const dirty = result.annotations !== null && !sameJson(result.annotations, value);
3592
+ const applyEnabled = !disabled && result.annotations !== null && dirty;
3593
+ const canRevert = buffer !== pretty(value);
3594
+ const apply = () => {
3595
+ if (!applyEnabled || result.annotations === null) return;
3596
+ onCommit(result.annotations);
3597
+ setDocChanged(false);
3598
+ };
3599
+ const revert = () => {
3600
+ setBuffer(pretty(value));
3601
+ setDocChanged(false);
3602
+ };
3603
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: sectionStyle, children: [
3604
+ showLabel !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SectionLabel, {}),
3605
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3606
+ JsonMonacoField,
3607
+ {
3608
+ buffer,
3609
+ disabled,
3610
+ modelUri: annotationsModelUri(modelKey),
3611
+ onChange: setBuffer,
3612
+ seed: buffer,
3613
+ testId: "annotations-json-editor"
3614
+ }
3615
+ ),
3616
+ result.error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", "data-testid": "annotations-error", style: errorStyle, children: result.error }),
3617
+ docChanged && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", "data-testid": "annotations-doc-changed", style: warnStyle, children: messages.inspector.annotationsDocChanged }),
3618
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3619
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3620
+ "button",
3621
+ {
3622
+ type: "button",
3623
+ onClick: apply,
3624
+ disabled: !applyEnabled,
3625
+ style: applyEnabled ? primaryBtn : disabledBtn,
3626
+ "data-testid": "inspector-annotations-apply",
3627
+ children: messages.inspector.annotationsApply
3628
+ }
3629
+ ),
3630
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtn, "data-testid": "inspector-annotations-revert", children: messages.inspector.annotationsRevert }),
3631
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: onRemove, style: dangerBtn, "data-testid": "inspector-annotations-remove", children: messages.inspector.annotationsRemove })
3632
+ ] })
3633
+ ] });
3634
+ }
3635
+ function SectionLabel() {
3636
+ const messages = useMessages();
3637
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: messages.inspector.annotations });
3638
+ }
3639
+ var sectionStyle = { display: "flex", flexDirection: "column", gap: 8 };
3640
+ var ghostBtn = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
3641
+ var primaryBtn = { ...ghostBtn, background: colors.primary, color: "white", borderColor: colors.primary };
3642
+ var disabledBtn = { ...primaryBtn, opacity: 0.5, cursor: "not-allowed" };
3643
+ var dangerBtn = { ...ghostBtn, background: colors.dangerBg, borderColor: colors.dangerBorder, color: colors.danger };
3644
+ var errorStyle = { color: colors.danger, fontSize: 11 };
3645
+ var warnStyle = { color: colors.warning, fontSize: 11 };
3646
+
3647
+ // src/inspector/WorkflowForm.tsx
3648
+ var import_jsx_runtime9 = require("react/jsx-runtime");
3328
3649
  function WorkflowForm({
3329
3650
  workflow,
3330
3651
  disabled,
3331
3652
  onDispatch
3332
3653
  }) {
3333
3654
  const messages = useMessages();
3334
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3335
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3655
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3656
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3336
3657
  TextField,
3337
3658
  {
3338
3659
  label: messages.inspector.name,
@@ -3342,7 +3663,7 @@ function WorkflowForm({
3342
3663
  testId: "inspector-workflow-name"
3343
3664
  }
3344
3665
  ),
3345
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3666
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3346
3667
  TextField,
3347
3668
  {
3348
3669
  label: messages.inspector.version,
@@ -3357,7 +3678,7 @@ function WorkflowForm({
3357
3678
  testId: "inspector-workflow-version"
3358
3679
  }
3359
3680
  ),
3360
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3681
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3361
3682
  TextField,
3362
3683
  {
3363
3684
  label: messages.inspector.description,
@@ -3373,7 +3694,7 @@ function WorkflowForm({
3373
3694
  testId: "inspector-workflow-desc"
3374
3695
  }
3375
3696
  ),
3376
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3697
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3377
3698
  CheckboxField,
3378
3699
  {
3379
3700
  label: messages.inspector.active,
@@ -3387,7 +3708,7 @@ function WorkflowForm({
3387
3708
  testId: "inspector-workflow-active"
3388
3709
  }
3389
3710
  ),
3390
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3711
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3391
3712
  TextField,
3392
3713
  {
3393
3714
  label: messages.inspector.initialState,
@@ -3401,14 +3722,24 @@ function WorkflowForm({
3401
3722
  }),
3402
3723
  testId: "inspector-workflow-initial"
3403
3724
  }
3725
+ ),
3726
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3727
+ AnnotationsField,
3728
+ {
3729
+ value: workflow.annotations,
3730
+ disabled,
3731
+ modelKey: `workflow-${workflow.name}`,
3732
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name }, annotations }),
3733
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "workflow", workflow: workflow.name } })
3734
+ }
3404
3735
  )
3405
3736
  ] });
3406
3737
  }
3407
3738
 
3408
3739
  // src/inspector/StateForm.tsx
3409
- var import_react8 = require("react");
3410
- var import_workflow_core3 = require("@cyoda/workflow-core");
3411
- var import_jsx_runtime8 = require("react/jsx-runtime");
3740
+ var import_react11 = require("react");
3741
+ var import_workflow_core4 = require("@cyoda/workflow-core");
3742
+ var import_jsx_runtime10 = require("react/jsx-runtime");
3412
3743
  function StateForm({
3413
3744
  workflow,
3414
3745
  stateCode,
@@ -3419,7 +3750,7 @@ function StateForm({
3419
3750
  onRequestDelete
3420
3751
  }) {
3421
3752
  const messages = useMessages();
3422
- const [renameError, setRenameError] = (0, import_react8.useState)(null);
3753
+ const [renameError, setRenameError] = (0, import_react11.useState)(null);
3423
3754
  const outgoing = state.transitions.length;
3424
3755
  const incoming = Object.values(workflow.states).reduce(
3425
3756
  (n, s) => n + s.transitions.filter((t) => t.next === stateCode).length,
@@ -3432,7 +3763,7 @@ function StateForm({
3432
3763
  const handleRename = (next) => {
3433
3764
  if (next === stateCode) return;
3434
3765
  setRenameError(null);
3435
- if (!import_workflow_core3.NAME_REGEX.test(next)) {
3766
+ if (!import_workflow_core4.NAME_REGEX.test(next)) {
3436
3767
  setRenameError(`"${next}" is not a valid state name`);
3437
3768
  return;
3438
3769
  }
@@ -3442,8 +3773,8 @@ function StateForm({
3442
3773
  }
3443
3774
  onDispatch({ op: "renameState", workflow: workflow.name, from: stateCode, to: next });
3444
3775
  };
3445
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3446
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3776
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
3777
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3447
3778
  TextField,
3448
3779
  {
3449
3780
  label: messages.inspector.name,
@@ -3454,29 +3785,29 @@ function StateForm({
3454
3785
  testId: "inspector-state-name"
3455
3786
  }
3456
3787
  ),
3457
- renameError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
3458
- (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3459
- isInitial && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
3460
- isTerminal && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
3461
- isUnreachable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
3788
+ renameError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
3789
+ (isInitial || isTerminal || isUnreachable) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
3790
+ isInitial && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: "#15803d", bg: "#f0fdf4", label: "Initial" }),
3791
+ isTerminal && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: "#0369a1", bg: "#eff6ff", label: "Terminal" }),
3792
+ isUnreachable && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StateBadge, { color: colors.warning, bg: colors.warningBg, label: "Unreachable" })
3462
3793
  ] }),
3463
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3794
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { fontSize: 12, color: colors.textSecondary }, children: [
3464
3795
  outgoing,
3465
3796
  " outgoing \xB7 ",
3466
3797
  incoming,
3467
3798
  " incoming"
3468
3799
  ] }),
3469
- !isInitial && !disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3800
+ !isInitial && !disabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3470
3801
  "button",
3471
3802
  {
3472
3803
  type: "button",
3473
3804
  onClick: () => onDispatch({ op: "setInitialState", workflow: workflow.name, stateCode }),
3474
- style: ghostBtn,
3805
+ style: ghostBtn2,
3475
3806
  "data-testid": "inspector-state-set-initial",
3476
3807
  children: "Set as Initial State"
3477
3808
  }
3478
3809
  ),
3479
- issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3810
+ issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3480
3811
  "div",
3481
3812
  {
3482
3813
  role: "alert",
@@ -3492,21 +3823,31 @@ function StateForm({
3492
3823
  },
3493
3824
  `${issue.code}-${i}`
3494
3825
  )) }),
3495
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3826
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3827
+ AnnotationsField,
3828
+ {
3829
+ value: state.annotations,
3830
+ disabled,
3831
+ modelKey: `state-${workflow.name}-${stateCode}`,
3832
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode }, annotations }),
3833
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "state", workflow: workflow.name, stateCode } })
3834
+ }
3835
+ ),
3836
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3496
3837
  "button",
3497
3838
  {
3498
3839
  type: "button",
3499
3840
  onClick: onRequestDelete,
3500
3841
  disabled,
3501
3842
  "data-testid": "inspector-state-delete",
3502
- style: dangerBtn,
3843
+ style: dangerBtn2,
3503
3844
  children: "Delete state\u2026"
3504
3845
  }
3505
3846
  )
3506
3847
  ] });
3507
3848
  }
3508
3849
  function StateBadge({ color, bg, label }) {
3509
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3850
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3510
3851
  "span",
3511
3852
  {
3512
3853
  style: {
@@ -3538,7 +3879,7 @@ function reachableStates(wf) {
3538
3879
  }
3539
3880
  return visited;
3540
3881
  }
3541
- var ghostBtn = {
3882
+ var ghostBtn2 = {
3542
3883
  alignSelf: "flex-start",
3543
3884
  padding: "5px 10px",
3544
3885
  background: "white",
@@ -3547,7 +3888,7 @@ var ghostBtn = {
3547
3888
  fontSize: 13,
3548
3889
  cursor: "pointer"
3549
3890
  };
3550
- var dangerBtn = {
3891
+ var dangerBtn2 = {
3551
3892
  alignSelf: "flex-start",
3552
3893
  padding: "6px 10px",
3553
3894
  background: colors.dangerBg,
@@ -3559,65 +3900,227 @@ var dangerBtn = {
3559
3900
  };
3560
3901
 
3561
3902
  // src/inspector/TransitionForm.tsx
3562
- var import_react14 = require("react");
3563
- var import_workflow_core6 = require("@cyoda/workflow-core");
3903
+ var import_react15 = require("react");
3904
+ var import_workflow_core7 = require("@cyoda/workflow-core");
3564
3905
 
3565
- // src/inspector/CriterionForm.tsx
3906
+ // src/inspector/CriterionField.tsx
3566
3907
  var import_react12 = require("react");
3908
+ var import_workflow_monaco = require("@cyoda/workflow-monaco");
3567
3909
 
3568
- // src/modals/DeleteStateModal.tsx
3569
- var import_react9 = require("react");
3570
- var import_jsx_runtime9 = require("react/jsx-runtime");
3571
- function countAffected(doc, workflow, stateCode) {
3572
- let outgoing = 0;
3573
- let incoming = 0;
3574
- const wf = doc.session.workflows.find((w) => w.name === workflow);
3575
- if (!wf) return { outgoing, incoming };
3576
- for (const [code, state] of Object.entries(wf.states)) {
3577
- for (const t of state.transitions) {
3578
- if (code === stateCode) outgoing++;
3579
- if (t.next === stateCode && code !== stateCode) incoming++;
3910
+ // src/inspector/criterionJson.ts
3911
+ var import_workflow_core5 = require("@cyoda/workflow-core");
3912
+ function criterionModelUri(key) {
3913
+ return `cyoda://criterion/${key}.json`;
3914
+ }
3915
+ function zodMessage(error) {
3916
+ const first = error.issues[0];
3917
+ if (!first) return "Invalid criterion.";
3918
+ const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3919
+ return `${first.message}${path}`;
3920
+ }
3921
+ function parseCriterionJson(text) {
3922
+ let raw;
3923
+ try {
3924
+ raw = JSON.parse(text);
3925
+ } catch {
3926
+ return { criterion: null, error: "Invalid JSON." };
3927
+ }
3928
+ const res = import_workflow_core5.CriterionSchema.safeParse(raw);
3929
+ if (res.success) {
3930
+ const blocking = (0, import_workflow_core5.criterionBlockingError)(res.data);
3931
+ if (blocking) return { criterion: null, error: blocking };
3932
+ return { criterion: res.data, error: null };
3933
+ }
3934
+ let friendly = null;
3935
+ if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3936
+ try {
3937
+ friendly = (0, import_workflow_core5.criterionBlockingError)(raw);
3938
+ } catch {
3939
+ friendly = null;
3580
3940
  }
3581
3941
  }
3582
- return { outgoing, incoming };
3942
+ return { criterion: null, error: friendly ?? zodMessage(res.error) };
3583
3943
  }
3584
- function DeleteStateModal({
3585
- document: doc,
3586
- workflow,
3587
- stateCode,
3588
- onConfirm,
3589
- onCancel
3590
- }) {
3591
- const messages = useMessages();
3592
- const counts = (0, import_react9.useMemo)(
3593
- () => countAffected(doc, workflow, stateCode),
3594
- [doc, workflow, stateCode]
3595
- );
3596
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ModalFrame, { onCancel, children: [
3597
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
3598
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
3599
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
3600
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: stateCode }),
3601
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { color: colors.textSecondary }, children: [
3602
- messages.confirmDelete.transitionsAffected,
3603
- ": ",
3604
- counts.outgoing + counts.incoming
3605
- ] })
3606
- ] }),
3607
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
3608
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn2, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
3609
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: onConfirm, style: dangerBtn2, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
3610
- ] })
3611
- ] });
3944
+
3945
+ // src/inspector/CriterionField.tsx
3946
+ var import_jsx_runtime11 = require("react/jsx-runtime");
3947
+ function defaultSimpleCriterion() {
3948
+ return { type: "simple", jsonPath: "", operation: "EQUALS" };
3612
3949
  }
3613
- function ModalFrame({
3614
- children,
3615
- onCancel,
3616
- labelledBy
3950
+ var pretty2 = (c) => JSON.stringify(c, null, 2);
3951
+ function CriterionField(props) {
3952
+ const m = useMessages().criterion;
3953
+ if (props.value === void 0) {
3954
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3955
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: summaryTextStyle, children: props.manual ? m.noneManual : m.noneAutomated }),
3956
+ !props.manual && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: warnStyle2, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3957
+ !props.disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: primaryBtnStyle, "data-testid": "inspector-criterion-add", onClick: () => props.onCommit(defaultSimpleCriterion()), children: m.add })
3958
+ ] });
3959
+ }
3960
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CriterionEditor, { ...props, value: props.value }, props.modelKey);
3961
+ }
3962
+ function CriterionEditor({ value, disabled, modelKey, onCommit, onRemove }) {
3963
+ const messages = useMessages();
3964
+ const m = messages.criterion;
3965
+ const [expanded, setExpanded] = (0, import_react12.useState)(false);
3966
+ const [buffer, setBuffer] = (0, import_react12.useState)(() => pretty2(value));
3967
+ const [docChanged, setDocChanged] = (0, import_react12.useState)(false);
3968
+ const prevValueRef = (0, import_react12.useRef)(value);
3969
+ (0, import_react12.useEffect)(() => {
3970
+ if (sameJson(prevValueRef.current, value)) return;
3971
+ const parsed = parseCriterionJson(buffer).criterion;
3972
+ if (parsed !== null && sameJson(parsed, value)) {
3973
+ setDocChanged(false);
3974
+ } else if (parsed !== null && sameJson(parsed, prevValueRef.current)) {
3975
+ setBuffer(pretty2(value));
3976
+ setDocChanged(false);
3977
+ } else {
3978
+ setDocChanged(true);
3979
+ }
3980
+ prevValueRef.current = value;
3981
+ }, [value, buffer]);
3982
+ const result = parseCriterionJson(buffer);
3983
+ const dirty = result.criterion !== null && !sameJson(result.criterion, value);
3984
+ const applyEnabled = !disabled && result.criterion !== null && dirty;
3985
+ const canRevert = buffer !== pretty2(value);
3986
+ const apply = () => {
3987
+ if (!applyEnabled || result.criterion === null) return;
3988
+ onCommit(result.criterion);
3989
+ setDocChanged(false);
3990
+ setExpanded(false);
3991
+ };
3992
+ const revert = () => {
3993
+ setBuffer(pretty2(value));
3994
+ setDocChanged(false);
3995
+ };
3996
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3997
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3998
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: metaChipStyle, children: value.type }),
3999
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { flex: 1 } }),
4000
+ !disabled && !expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: ghostBtnStyle, "data-testid": "inspector-criterion-edit", onClick: () => setExpanded(true), children: m.edit }),
4001
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", style: destructiveBtnStyle, "data-testid": "inspector-criterion-remove", onClick: onRemove, children: m.remove })
4002
+ ] }),
4003
+ !expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CompactJson, { criterion: value }),
4004
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
4005
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4006
+ JsonMonacoField,
4007
+ {
4008
+ buffer,
4009
+ disabled,
4010
+ modelUri: criterionModelUri(modelKey),
4011
+ onChange: setBuffer,
4012
+ seed: buffer,
4013
+ registerSchema: import_workflow_monaco.registerCriterionSchema,
4014
+ testId: "criterion-json-editor"
4015
+ }
4016
+ ),
4017
+ result.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", "data-testid": "criterion-error", style: errorStyle2, children: result.error }),
4018
+ docChanged && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", "data-testid": "criterion-doc-changed", style: warnLineStyle, children: messages.inspector.annotationsDocChanged }),
4019
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4020
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: apply, disabled: !applyEnabled, style: applyEnabled ? primaryBtnStyle : { ...primaryBtnStyle, opacity: 0.5, cursor: "not-allowed" }, "data-testid": "inspector-criterion-apply", children: m.applyModal }),
4021
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: revert, disabled: !canRevert, style: ghostBtnStyle, "data-testid": "inspector-criterion-revert", children: m.revert }),
4022
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: () => setExpanded(false), style: ghostBtnStyle, "data-testid": "inspector-criterion-collapse", children: m.collapse })
4023
+ ] })
4024
+ ] })
4025
+ ] });
4026
+ }
4027
+ function CompactJson({ criterion }) {
4028
+ const text = JSON.stringify(criterion);
4029
+ const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
4030
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { "data-testid": "criterion-compact-json", style: { display: "block", fontFamily: fonts.mono, fontSize: 11, color: colors.textSecondary, background: colors.surfaceMuted, padding: "6px 8px", borderRadius: radii.sm, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: display });
4031
+ }
4032
+ var cardStyle = { display: "flex", flexDirection: "column", gap: 8, padding: 10, border: `1px solid ${colors.border}`, borderRadius: radii.md, background: colors.surface };
4033
+ var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
4034
+ var warnStyle2 = { margin: 0, padding: "6px 8px", background: colors.warningBg, border: `1px solid ${colors.warningBorder}`, borderRadius: radii.sm, color: colors.warning, fontSize: 11 };
4035
+ var errorStyle2 = { color: colors.danger, fontSize: 11 };
4036
+ var warnLineStyle = { color: colors.warning, fontSize: 11 };
4037
+
4038
+ // src/inspector/CriterionForm.tsx
4039
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4040
+ function criterionModelKey(host) {
4041
+ if (host.kind === "transition") return `transition-${host.transitionUuid}`;
4042
+ if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
4043
+ return `host-${host.workflow}`;
4044
+ }
4045
+ function CriterionSection({
4046
+ host,
4047
+ manual,
4048
+ criterion,
4049
+ disabled,
4050
+ onDispatch,
4051
+ onSelectionChange: _onSelectionChange
3617
4052
  }) {
3618
- const frameRef = (0, import_react9.useRef)(null);
3619
- const previousFocusRef = (0, import_react9.useRef)(null);
3620
- (0, import_react9.useEffect)(() => {
4053
+ const path = ["criterion"];
4054
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4055
+ CriterionField,
4056
+ {
4057
+ value: criterion,
4058
+ manual,
4059
+ disabled,
4060
+ modelKey: criterionModelKey(host),
4061
+ onCommit: (next) => onDispatch({ op: "setCriterion", host, path, criterion: next }),
4062
+ onRemove: () => onDispatch({ op: "setCriterion", host, path, criterion: void 0 })
4063
+ }
4064
+ );
4065
+ }
4066
+
4067
+ // src/inspector/ProcessorForm.tsx
4068
+ var import_react14 = require("react");
4069
+ var import_workflow_core6 = require("@cyoda/workflow-core");
4070
+
4071
+ // src/modals/DeleteStateModal.tsx
4072
+ var import_react13 = require("react");
4073
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4074
+ function countAffected(doc, workflow, stateCode) {
4075
+ let outgoing = 0;
4076
+ let incoming = 0;
4077
+ const wf = doc.session.workflows.find((w) => w.name === workflow);
4078
+ if (!wf) return { outgoing, incoming };
4079
+ for (const [code, state] of Object.entries(wf.states)) {
4080
+ for (const t of state.transitions) {
4081
+ if (code === stateCode) outgoing++;
4082
+ if (t.next === stateCode && code !== stateCode) incoming++;
4083
+ }
4084
+ }
4085
+ return { outgoing, incoming };
4086
+ }
4087
+ function DeleteStateModal({
4088
+ document: doc,
4089
+ workflow,
4090
+ stateCode,
4091
+ onConfirm,
4092
+ onCancel
4093
+ }) {
4094
+ const messages = useMessages();
4095
+ const counts = (0, import_react13.useMemo)(
4096
+ () => countAffected(doc, workflow, stateCode),
4097
+ [doc, workflow, stateCode]
4098
+ );
4099
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ModalFrame, { onCancel, children: [
4100
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.confirmDelete.title }),
4101
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: messages.confirmDelete.message }),
4102
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { padding: 8, background: colors.surfaceMuted, border: `1px solid ${colors.borderSubtle}`, borderRadius: radii.sm, fontSize: 13 }, children: [
4103
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: stateCode }),
4104
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { color: colors.textSecondary }, children: [
4105
+ messages.confirmDelete.transitionsAffected,
4106
+ ": ",
4107
+ counts.outgoing + counts.incoming
4108
+ ] })
4109
+ ] }),
4110
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
4111
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "modal-delete-cancel", children: messages.confirmDelete.cancel }),
4112
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: onConfirm, style: dangerBtn3, "data-testid": "modal-delete-confirm", children: messages.confirmDelete.confirm })
4113
+ ] })
4114
+ ] });
4115
+ }
4116
+ function ModalFrame({
4117
+ children,
4118
+ onCancel,
4119
+ labelledBy
4120
+ }) {
4121
+ const frameRef = (0, import_react13.useRef)(null);
4122
+ const previousFocusRef = (0, import_react13.useRef)(null);
4123
+ (0, import_react13.useEffect)(() => {
3621
4124
  previousFocusRef.current = document.activeElement ?? null;
3622
4125
  const node = frameRef.current;
3623
4126
  if (node) {
@@ -3630,7 +4133,7 @@ function ModalFrame({
3630
4133
  previousFocusRef.current?.focus?.();
3631
4134
  };
3632
4135
  }, []);
3633
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4136
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3634
4137
  "div",
3635
4138
  {
3636
4139
  onClick: onCancel,
@@ -3650,7 +4153,7 @@ function ModalFrame({
3650
4153
  zIndex: 1e3
3651
4154
  },
3652
4155
  "data-testid": "modal-backdrop",
3653
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4156
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3654
4157
  "div",
3655
4158
  {
3656
4159
  ref: frameRef,
@@ -3676,7 +4179,7 @@ function ModalFrame({
3676
4179
  }
3677
4180
  );
3678
4181
  }
3679
- var ghostBtn2 = {
4182
+ var ghostBtn3 = {
3680
4183
  padding: "6px 12px",
3681
4184
  background: "white",
3682
4185
  border: `1px solid ${colors.border}`,
@@ -3684,456 +4187,15 @@ var ghostBtn2 = {
3684
4187
  fontSize: 13,
3685
4188
  cursor: "pointer"
3686
4189
  };
3687
- var dangerBtn2 = {
3688
- ...ghostBtn2,
4190
+ var dangerBtn3 = {
4191
+ ...ghostBtn3,
3689
4192
  background: colors.danger,
3690
4193
  color: "white",
3691
4194
  borderColor: colors.danger
3692
4195
  };
3693
4196
 
3694
- // src/inspector/CriterionJsonEditor.tsx
3695
- var import_react11 = require("react");
3696
- var import_workflow_monaco = require("@cyoda/workflow-monaco");
3697
-
3698
- // src/inspector/CriterionMonacoContext.tsx
3699
- var import_react10 = require("react");
3700
- var CriterionMonacoContext = (0, import_react10.createContext)(null);
3701
- var CriterionMonacoProvider = CriterionMonacoContext.Provider;
3702
- function useCriterionMonaco() {
3703
- return (0, import_react10.useContext)(CriterionMonacoContext);
3704
- }
3705
-
3706
- // src/components/monacoDisposal.ts
3707
- var installed = false;
3708
- function isMonacoCanceled(reason) {
3709
- if (reason == null || typeof reason !== "object") return false;
3710
- return reason.name === "Canceled";
3711
- }
3712
- function installMonacoCancellationFilter() {
3713
- if (installed || typeof window === "undefined") return;
3714
- installed = true;
3715
- window.addEventListener("unhandledrejection", (e) => {
3716
- if (isMonacoCanceled(e.reason)) e.preventDefault();
3717
- });
3718
- }
3719
- installMonacoCancellationFilter();
3720
-
3721
- // src/inspector/criterionJson.ts
3722
- var import_workflow_core4 = require("@cyoda/workflow-core");
3723
- function criterionModelUri(key) {
3724
- return `cyoda://criterion/${key}.json`;
3725
- }
3726
- function zodMessage(error) {
3727
- const first = error.issues[0];
3728
- if (!first) return "Invalid criterion.";
3729
- const path = first.path.length ? ` at ${first.path.join(".")}` : "";
3730
- return `${first.message}${path}`;
3731
- }
3732
- function parseCriterionJson(text) {
3733
- let raw;
3734
- try {
3735
- raw = JSON.parse(text);
3736
- } catch {
3737
- return { criterion: null, error: "Invalid JSON." };
3738
- }
3739
- const res = import_workflow_core4.CriterionSchema.safeParse(raw);
3740
- if (res.success) {
3741
- const blocking = (0, import_workflow_core4.criterionBlockingError)(res.data);
3742
- if (blocking) return { criterion: null, error: blocking };
3743
- return { criterion: res.data, error: null };
3744
- }
3745
- let friendly = null;
3746
- if (typeof raw === "object" && raw !== null && typeof raw.type === "string") {
3747
- try {
3748
- friendly = (0, import_workflow_core4.criterionBlockingError)(raw);
3749
- } catch {
3750
- friendly = null;
3751
- }
3752
- }
3753
- return { criterion: null, error: friendly ?? zodMessage(res.error) };
3754
- }
3755
-
3756
- // src/inspector/CriterionJsonEditor.tsx
3757
- var import_jsx_runtime10 = require("react/jsx-runtime");
3758
- function CriterionJsonEditor({ value, disabled, modelKey, onChange }) {
3759
- const monaco = useCriterionMonaco();
3760
- const onChangeRef = (0, import_react11.useRef)(onChange);
3761
- onChangeRef.current = onChange;
3762
- const initialText = (0, import_react11.useRef)(JSON.stringify(value, null, 2)).current;
3763
- if (monaco) {
3764
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3765
- MonacoCriterionEditor,
3766
- {
3767
- monaco,
3768
- initialText,
3769
- disabled,
3770
- modelKey,
3771
- onChangeRef
3772
- }
3773
- );
3774
- }
3775
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3776
- TextareaCriterionEditor,
3777
- {
3778
- initialText,
3779
- disabled,
3780
- onChangeRef
3781
- }
3782
- );
3783
- }
3784
- function TextareaCriterionEditor({
3785
- initialText,
3786
- disabled,
3787
- onChangeRef
3788
- }) {
3789
- (0, import_react11.useEffect)(() => {
3790
- onChangeRef.current(parseCriterionJson(initialText));
3791
- }, [initialText, onChangeRef]);
3792
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3793
- "textarea",
3794
- {
3795
- defaultValue: initialText,
3796
- disabled,
3797
- rows: 16,
3798
- "data-testid": "criterion-json-editor",
3799
- style: jsonTextAreaStyle,
3800
- onChange: (e) => onChangeRef.current(parseCriterionJson(e.target.value))
3801
- }
3802
- );
3803
- }
3804
- function MonacoCriterionEditor({
3805
- monaco,
3806
- initialText,
3807
- disabled,
3808
- modelKey,
3809
- onChangeRef
3810
- }) {
3811
- const containerRef = (0, import_react11.useRef)(null);
3812
- const editorRef = (0, import_react11.useRef)(null);
3813
- (0, import_react11.useEffect)(() => {
3814
- if (!containerRef.current || editorRef.current) return;
3815
- const model = monaco.editor.createModel(
3816
- initialText,
3817
- "json",
3818
- monaco.Uri.parse(criterionModelUri(modelKey))
3819
- );
3820
- const editor = monaco.editor.create(containerRef.current, {
3821
- model,
3822
- automaticLayout: true,
3823
- minimap: { enabled: false },
3824
- fontSize: 13,
3825
- tabSize: 2,
3826
- scrollBeyondLastLine: false,
3827
- theme: "vs",
3828
- readOnly: disabled
3829
- });
3830
- editorRef.current = editor;
3831
- installMonacoCancellationFilter();
3832
- const schemaHandle = (0, import_workflow_monaco.registerCriterionSchema)(monaco);
3833
- const report = () => onChangeRef.current(parseCriterionJson(model.getValue()));
3834
- report();
3835
- const sub = model.onDidChangeContent(report);
3836
- return () => {
3837
- sub.dispose();
3838
- schemaHandle.dispose();
3839
- editor.dispose();
3840
- editorRef.current = null;
3841
- model.dispose();
3842
- };
3843
- }, [monaco, modelKey]);
3844
- (0, import_react11.useEffect)(() => {
3845
- editorRef.current?.updateOptions?.({ readOnly: disabled });
3846
- }, [disabled]);
3847
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3848
- "div",
3849
- {
3850
- ref: containerRef,
3851
- "data-testid": "criterion-json-editor",
3852
- style: { height: 320, border: `1px solid ${colors.border}`, borderRadius: radii.sm }
3853
- }
3854
- );
3855
- }
3856
- var jsonTextAreaStyle = {
3857
- fontFamily: fonts.mono,
3858
- fontSize: 12,
3859
- padding: 8,
3860
- borderWidth: 1,
3861
- borderStyle: "solid",
3862
- borderColor: colors.border,
3863
- borderRadius: radii.sm,
3864
- background: "white",
3865
- resize: "vertical"
3866
- };
3867
-
3868
- // src/inspector/CriterionForm.tsx
3869
- var import_jsx_runtime11 = require("react/jsx-runtime");
3870
- function defaultCriterion(type) {
3871
- switch (type) {
3872
- case "simple":
3873
- return { type: "simple", jsonPath: "", operation: "EQUALS" };
3874
- case "group":
3875
- return { type: "group", operator: "AND", conditions: [] };
3876
- case "function":
3877
- return { type: "function", function: { name: "" } };
3878
- case "lifecycle":
3879
- return { type: "lifecycle", field: "state", operation: "EQUALS" };
3880
- case "array":
3881
- return { type: "array", jsonPath: "", operation: "EQUALS", value: [] };
3882
- }
3883
- }
3884
- function CriterionSection({
3885
- host,
3886
- stateCode,
3887
- transitionName,
3888
- targetState,
3889
- manual,
3890
- criterion,
3891
- disabled,
3892
- onDispatch,
3893
- onSelectionChange
3894
- }) {
3895
- const messages = useMessages();
3896
- const [modalOpen, setModalOpen] = (0, import_react12.useState)(false);
3897
- const path = ["criterion"];
3898
- const removeCriterion = () => {
3899
- onDispatch({ op: "setCriterion", host, path, criterion: void 0 });
3900
- if (host.kind === "transition") {
3901
- onSelectionChange?.({ kind: "transition", transitionUuid: host.transitionUuid });
3902
- }
3903
- };
3904
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3905
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3906
- CriterionSummaryCard,
3907
- {
3908
- criterion,
3909
- disabled,
3910
- manual,
3911
- onAdd: () => setModalOpen(true),
3912
- onEdit: () => setModalOpen(true),
3913
- onRemove: removeCriterion
3914
- }
3915
- ),
3916
- modalOpen && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3917
- CriterionEditorModal,
3918
- {
3919
- title: criterion ? messages.criterion.editTitle : messages.criterion.addTitle,
3920
- context: `${stateCode ?? host.workflow} \u2192 ${transitionName ?? "transition"} \u2192 ${targetState ?? ""}`,
3921
- host,
3922
- path,
3923
- initialCriterion: criterion,
3924
- disabled,
3925
- onDispatch,
3926
- onCancel: () => setModalOpen(false),
3927
- onApplied: () => {
3928
- setModalOpen(false);
3929
- if (host.kind === "transition") {
3930
- const selection = {
3931
- kind: "transition",
3932
- transitionUuid: host.transitionUuid
3933
- };
3934
- onSelectionChange?.(selection);
3935
- window.setTimeout(() => onSelectionChange?.(selection), 100);
3936
- }
3937
- }
3938
- }
3939
- )
3940
- ] });
3941
- }
3942
- function CriterionSummaryCard({
3943
- criterion,
3944
- disabled,
3945
- manual,
3946
- onAdd,
3947
- onEdit,
3948
- onRemove
3949
- }) {
3950
- const messages = useMessages();
3951
- const m = messages.criterion;
3952
- if (!criterion) {
3953
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3954
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SectionHeader, { label: m.heading, badge: "none" }),
3955
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: summaryTextStyle, children: manual ? m.noneManual : m.noneAutomated }),
3956
- !manual && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: warningCardStyle, "data-testid": "criterion-automated-warning", children: m.noneAutomatedWarning }),
3957
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3958
- "button",
3959
- {
3960
- type: "button",
3961
- onClick: onAdd,
3962
- style: primaryBtn,
3963
- "data-testid": "inspector-criterion-add",
3964
- children: m.add
3965
- }
3966
- )
3967
- ] });
3968
- }
3969
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: cardStyle, "data-testid": "criterion-summary-card", children: [
3970
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SectionHeader, { label: m.heading, badge: criterion.type }),
3971
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CriterionCompactJson, { criterion }),
3972
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [
3973
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3974
- "button",
3975
- {
3976
- type: "button",
3977
- onClick: onEdit,
3978
- style: ghostBtn3,
3979
- "data-testid": "inspector-criterion-edit",
3980
- children: m.edit
3981
- }
3982
- ),
3983
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3984
- "button",
3985
- {
3986
- type: "button",
3987
- onClick: onRemove,
3988
- style: dangerBtn3,
3989
- "data-testid": "inspector-criterion-remove",
3990
- children: m.remove
3991
- }
3992
- )
3993
- ] })
3994
- ] });
3995
- }
3996
- function CriterionCompactJson({ criterion }) {
3997
- const text = JSON.stringify(criterion);
3998
- const display = text.length > 140 ? `${text.slice(0, 137)}\u2026` : text;
3999
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4000
- "code",
4001
- {
4002
- "data-testid": "criterion-compact-json",
4003
- style: {
4004
- display: "block",
4005
- fontFamily: fonts.mono,
4006
- fontSize: 11,
4007
- color: colors.textSecondary,
4008
- background: colors.surfaceMuted,
4009
- padding: "6px 8px",
4010
- borderRadius: radii.sm,
4011
- whiteSpace: "pre-wrap",
4012
- wordBreak: "break-word"
4013
- },
4014
- children: display
4015
- }
4016
- );
4017
- }
4018
- function criterionModelKey(host) {
4019
- if (host.kind === "transition") return `transition-${host.transitionUuid}`;
4020
- if (host.kind === "processorConfig") return `processor-${host.processorUuid}`;
4021
- return `host-${host.workflow}`;
4022
- }
4023
- function CriterionEditorModal({
4024
- title,
4025
- context,
4026
- host,
4027
- path,
4028
- initialCriterion,
4029
- disabled,
4030
- onDispatch,
4031
- onCancel,
4032
- onApplied
4033
- }) {
4034
- const messages = useMessages();
4035
- const seed = initialCriterion ?? defaultCriterion("simple");
4036
- const [result, setResult] = (0, import_react12.useState)(
4037
- () => parseCriterionJson(JSON.stringify(seed))
4038
- );
4039
- const modelKey = criterionModelKey(host);
4040
- const applyDisabled = disabled || result.criterion === null;
4041
- const apply = () => {
4042
- if (applyDisabled || !result.criterion) return;
4043
- onDispatch({ op: "setCriterion", host, path, criterion: result.criterion });
4044
- onApplied();
4045
- };
4046
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ModalFrame, { onCancel, labelledBy: "criterion-modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: modalStyle, "data-testid": "criterion-editor-modal", children: [
4047
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4048
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { id: "criterion-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4049
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: context })
4050
- ] }),
4051
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: modalBodyStyle, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4052
- CriterionJsonEditor,
4053
- {
4054
- value: seed,
4055
- disabled,
4056
- modelKey,
4057
- onChange: setResult
4058
- }
4059
- ) }),
4060
- result.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: errorStyle, "data-testid": "criterion-modal-blocking-error", children: result.error }),
4061
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("footer", { style: modalFooterStyle, children: [
4062
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { flex: 1 } }),
4063
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn3, "data-testid": "criterion-modal-cancel", children: messages.criterion.cancel }),
4064
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4065
- "button",
4066
- {
4067
- type: "button",
4068
- onClick: apply,
4069
- disabled: applyDisabled,
4070
- style: applyDisabled ? disabledPrimaryBtn : primaryBtn,
4071
- "data-testid": "criterion-modal-apply",
4072
- children: messages.criterion.applyModal
4073
- }
4074
- )
4075
- ] })
4076
- ] }) });
4077
- }
4078
- function SectionHeader({ label, badge }) {
4079
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
4080
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: label }),
4081
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 11, padding: "1px 6px", background: colors.surfaceMuted, borderRadius: radii.pill, color: colors.textTertiary }, children: badge })
4082
- ] });
4083
- }
4084
- var cardStyle = {
4085
- display: "flex",
4086
- flexDirection: "column",
4087
- gap: 8,
4088
- padding: 10,
4089
- border: `1px solid ${colors.border}`,
4090
- borderRadius: radii.md,
4091
- background: "white"
4092
- };
4093
- var summaryTextStyle = { margin: 0, fontSize: 12, color: colors.textSecondary, lineHeight: 1.45 };
4094
- var warningCardStyle = {
4095
- margin: 0,
4096
- padding: "6px 8px",
4097
- background: colors.warningBg,
4098
- border: `1px solid ${colors.warningBorder}`,
4099
- borderRadius: radii.sm,
4100
- color: colors.warning,
4101
- fontSize: 11
4102
- };
4103
- var modalStyle = {
4104
- width: "min(760px, calc(100vw - 48px))",
4105
- maxHeight: "min(760px, calc(100vh - 72px))",
4106
- display: "flex",
4107
- flexDirection: "column",
4108
- gap: 14
4109
- };
4110
- var modalBodyStyle = {
4111
- overflow: "auto",
4112
- padding: 12,
4113
- border: `1px solid ${colors.borderSubtle}`,
4114
- borderRadius: radii.md,
4115
- background: colors.surfaceMuted
4116
- };
4117
- var modalFooterStyle = {
4118
- display: "flex",
4119
- alignItems: "center",
4120
- gap: 8,
4121
- position: "sticky",
4122
- bottom: 0,
4123
- paddingTop: 10,
4124
- borderTop: `1px solid ${colors.borderSubtle}`,
4125
- background: "white"
4126
- };
4127
- var ghostBtn3 = { padding: "6px 10px", background: "white", border: `1px solid ${colors.border}`, borderRadius: radii.sm, fontSize: 12, cursor: "pointer" };
4128
- var primaryBtn = { ...ghostBtn3, background: colors.primary, color: "white", borderColor: colors.primary };
4129
- var disabledPrimaryBtn = { ...primaryBtn, opacity: 0.5, cursor: "not-allowed" };
4130
- var dangerBtn3 = { ...ghostBtn3, background: colors.dangerBg, borderColor: colors.dangerBorder, color: colors.danger };
4131
- var errorStyle = { color: colors.danger, fontSize: 11 };
4132
-
4133
4197
  // src/inspector/ProcessorForm.tsx
4134
- var import_react13 = require("react");
4135
- var import_workflow_core5 = require("@cyoda/workflow-core");
4136
- var import_jsx_runtime12 = require("react/jsx-runtime");
4198
+ var import_jsx_runtime14 = require("react/jsx-runtime");
4137
4199
  var EXECUTION_MODES = [
4138
4200
  "ASYNC_NEW_TX",
4139
4201
  "ASYNC_SAME_TX",
@@ -4193,7 +4255,7 @@ function toProcessor(draft) {
4193
4255
  function validateDraft(draft, existingNames, originalName) {
4194
4256
  const name = draft.name.trim();
4195
4257
  if (name.length === 0) return "Processor name is required.";
4196
- if (!import_workflow_core5.NAME_REGEX.test(name)) {
4258
+ if (!import_workflow_core6.NAME_REGEX.test(name)) {
4197
4259
  return "Processor name must start with a letter and contain only letters, digits, underscores, or hyphens.";
4198
4260
  }
4199
4261
  if (existingNames.some((existing) => existing === name && existing !== originalName)) {
@@ -4230,8 +4292,8 @@ function ProcessorEditorModal({
4230
4292
  onCancel,
4231
4293
  onApply
4232
4294
  }) {
4233
- const [draft, setDraft] = (0, import_react13.useState)(() => toDraft(initialProcessor));
4234
- (0, import_react13.useEffect)(() => {
4295
+ const [draft, setDraft] = (0, import_react14.useState)(() => toDraft(initialProcessor));
4296
+ (0, import_react14.useEffect)(() => {
4235
4297
  setDraft(toDraft(initialProcessor));
4236
4298
  }, [initialProcessor]);
4237
4299
  const error = validateDraft(draft, existingNames, initialProcessor?.name);
@@ -4239,13 +4301,13 @@ function ProcessorEditorModal({
4239
4301
  if (disabled || error) return;
4240
4302
  onApply(toProcessor(draft));
4241
4303
  };
4242
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: modalStyle2, "data-testid": "processor-editor-modal", children: [
4243
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4244
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4245
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4304
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ModalFrame, { onCancel, labelledBy: "processor-modal-title", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: modalStyle, "data-testid": "processor-editor-modal", children: [
4305
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("header", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4306
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { id: "processor-modal-title", style: { margin: 0, fontSize: 18 }, children: title }),
4307
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { margin: 0, fontSize: 12, color: colors.textTertiary }, children: "Processor changes stay local until Apply." })
4246
4308
  ] }),
4247
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: modalBodyStyle2, children: [
4248
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4309
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: modalBodyStyle, children: [
4310
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4249
4311
  "input",
4250
4312
  {
4251
4313
  type: "text",
@@ -4255,7 +4317,7 @@ function ProcessorEditorModal({
4255
4317
  style: inputStyle2
4256
4318
  }
4257
4319
  ) }),
4258
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Execution mode", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4320
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Execution mode", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4259
4321
  CustomSelectInput,
4260
4322
  {
4261
4323
  value: draft.executionMode,
@@ -4264,8 +4326,8 @@ function ProcessorEditorModal({
4264
4326
  testId: "processor-execution-mode"
4265
4327
  }
4266
4328
  ) }),
4267
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { style: checkboxRowStyle, children: [
4268
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4329
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: checkboxRowStyle, children: [
4330
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4269
4331
  "input",
4270
4332
  {
4271
4333
  type: "checkbox",
@@ -4273,9 +4335,9 @@ function ProcessorEditorModal({
4273
4335
  onChange: (event) => setDraft((current) => ({ ...current, attachEntity: event.target.checked }))
4274
4336
  }
4275
4337
  ),
4276
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "Attach entity" })
4338
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Attach entity" })
4277
4339
  ] }),
4278
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4340
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Calculation node tags", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4279
4341
  "input",
4280
4342
  {
4281
4343
  type: "text",
@@ -4288,7 +4350,7 @@ function ProcessorEditorModal({
4288
4350
  style: inputStyle2
4289
4351
  }
4290
4352
  ) }),
4291
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4353
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Response timeout ms", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4292
4354
  "input",
4293
4355
  {
4294
4356
  type: "text",
@@ -4300,7 +4362,7 @@ function ProcessorEditorModal({
4300
4362
  style: inputStyle2
4301
4363
  }
4302
4364
  ) }),
4303
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Retry policy", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4365
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Retry policy", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4304
4366
  "input",
4305
4367
  {
4306
4368
  type: "text",
@@ -4309,8 +4371,8 @@ function ProcessorEditorModal({
4309
4371
  style: inputStyle2
4310
4372
  }
4311
4373
  ) }),
4312
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { style: checkboxRowStyle, children: [
4313
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4374
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: checkboxRowStyle, children: [
4375
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4314
4376
  "input",
4315
4377
  {
4316
4378
  type: "checkbox",
@@ -4323,9 +4385,9 @@ function ProcessorEditorModal({
4323
4385
  "data-testid": "processor-async-result"
4324
4386
  }
4325
4387
  ),
4326
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "Async result" })
4388
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Async result" })
4327
4389
  ] }),
4328
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4390
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FormField, { label: "Crossover to async ms", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4329
4391
  "input",
4330
4392
  {
4331
4393
  type: "text",
@@ -4340,16 +4402,16 @@ function ProcessorEditorModal({
4340
4402
  }
4341
4403
  ) })
4342
4404
  ] }),
4343
- error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "alert", style: errorStyle2, "data-testid": "processor-modal-error", children: error }),
4344
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("footer", { style: modalFooterStyle2, children: [
4345
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4346
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4405
+ error && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "alert", style: errorStyle3, "data-testid": "processor-modal-error", children: error }),
4406
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("footer", { style: modalFooterStyle, children: [
4407
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn4, "data-testid": "processor-modal-cancel", children: "Cancel" }),
4408
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4347
4409
  "button",
4348
4410
  {
4349
4411
  type: "button",
4350
4412
  onClick: apply,
4351
4413
  disabled: disabled || !!error,
4352
- style: disabled || error ? disabledPrimaryBtn2 : primaryBtn2,
4414
+ style: disabled || error ? disabledPrimaryBtn : primaryBtn2,
4353
4415
  "data-testid": "processor-modal-apply",
4354
4416
  children: "Apply processor"
4355
4417
  }
@@ -4361,8 +4423,8 @@ function FormField({
4361
4423
  label,
4362
4424
  children
4363
4425
  }) {
4364
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4365
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: labelStyle2, children: label }),
4426
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4427
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: labelStyle2, children: label }),
4366
4428
  children
4367
4429
  ] });
4368
4430
  }
@@ -4376,18 +4438,18 @@ function ProcessorForm({
4376
4438
  onDispatch
4377
4439
  }) {
4378
4440
  const messages = useMessages();
4379
- const [modalOpen, setModalOpen] = (0, import_react13.useState)(false);
4380
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: summaryCardStyle, children: [
4381
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4382
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4383
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
4384
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4441
+ const [modalOpen, setModalOpen] = (0, import_react14.useState)(false);
4442
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: summaryCardStyle, children: [
4443
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }, children: [
4444
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4445
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
4446
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: summarizeProcessor(processor) })
4385
4447
  ] }),
4386
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: chipStyle, children: processor.type })
4448
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: chipStyle, children: processor.type })
4387
4449
  ] }),
4388
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4389
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4390
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4450
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4451
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: () => setModalOpen(true), style: ghostBtn4, children: "Edit" }),
4452
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4391
4453
  "button",
4392
4454
  {
4393
4455
  type: "button",
@@ -4402,7 +4464,7 @@ function ProcessorForm({
4402
4464
  children: messages.inspector.moveUp
4403
4465
  }
4404
4466
  ),
4405
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4467
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4406
4468
  "button",
4407
4469
  {
4408
4470
  type: "button",
@@ -4417,7 +4479,7 @@ function ProcessorForm({
4417
4479
  children: messages.inspector.moveDown
4418
4480
  }
4419
4481
  ),
4420
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4482
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4421
4483
  "button",
4422
4484
  {
4423
4485
  type: "button",
@@ -4429,7 +4491,7 @@ function ProcessorForm({
4429
4491
  }
4430
4492
  )
4431
4493
  ] }),
4432
- modalOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4494
+ modalOpen && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4433
4495
  ProcessorEditorModal,
4434
4496
  {
4435
4497
  title: `Edit ${processor.name}`,
@@ -4466,18 +4528,18 @@ var disabledInputStyle = {
4466
4528
  background: colors.surfaceMuted,
4467
4529
  color: colors.textTertiary
4468
4530
  };
4469
- var modalStyle2 = {
4531
+ var modalStyle = {
4470
4532
  width: "min(760px, calc(100vw - 48px))",
4471
4533
  display: "flex",
4472
4534
  flexDirection: "column",
4473
4535
  gap: 16
4474
4536
  };
4475
- var modalBodyStyle2 = {
4537
+ var modalBodyStyle = {
4476
4538
  display: "grid",
4477
4539
  gridTemplateColumns: "1fr 1fr",
4478
4540
  gap: 12
4479
4541
  };
4480
- var modalFooterStyle2 = {
4542
+ var modalFooterStyle = {
4481
4543
  display: "flex",
4482
4544
  justifyContent: "flex-end",
4483
4545
  gap: 8
@@ -4491,7 +4553,7 @@ var checkboxRowStyle = {
4491
4553
  color: colors.textSecondary,
4492
4554
  cursor: "pointer"
4493
4555
  };
4494
- var errorStyle2 = {
4556
+ var errorStyle3 = {
4495
4557
  padding: "8px 10px",
4496
4558
  border: `1px solid ${colors.dangerBorder}`,
4497
4559
  background: colors.dangerBg,
@@ -4513,7 +4575,7 @@ var primaryBtn2 = {
4513
4575
  color: "white",
4514
4576
  borderColor: colors.primary
4515
4577
  };
4516
- var disabledPrimaryBtn2 = {
4578
+ var disabledPrimaryBtn = {
4517
4579
  ...primaryBtn2,
4518
4580
  opacity: 0.5,
4519
4581
  cursor: "not-allowed"
@@ -4543,7 +4605,7 @@ var summaryCardStyle = {
4543
4605
  };
4544
4606
 
4545
4607
  // src/inspector/TransitionForm.tsx
4546
- var import_jsx_runtime13 = require("react/jsx-runtime");
4608
+ var import_jsx_runtime15 = require("react/jsx-runtime");
4547
4609
  function TransitionForm({
4548
4610
  workflow,
4549
4611
  stateCode,
@@ -4558,15 +4620,15 @@ function TransitionForm({
4558
4620
  onSelectionChange
4559
4621
  }) {
4560
4622
  const messages = useMessages();
4561
- const [renameError, setRenameError] = (0, import_react14.useState)(null);
4562
- const [processorModal, setProcessorModal] = (0, import_react14.useState)(null);
4563
- const [scheduleDelayDraft, setScheduleDelayDraft] = (0, import_react14.useState)(
4623
+ const [renameError, setRenameError] = (0, import_react15.useState)(null);
4624
+ const [processorModal, setProcessorModal] = (0, import_react15.useState)(null);
4625
+ const [scheduleDelayDraft, setScheduleDelayDraft] = (0, import_react15.useState)(
4564
4626
  transition.schedule?.delayMs !== void 0 ? String(transition.schedule.delayMs) : ""
4565
4627
  );
4566
- const [scheduleTimeoutDraft, setScheduleTimeoutDraft] = (0, import_react14.useState)(
4628
+ const [scheduleTimeoutDraft, setScheduleTimeoutDraft] = (0, import_react15.useState)(
4567
4629
  transition.schedule?.timeoutMs !== void 0 ? String(transition.schedule.timeoutMs) : ""
4568
4630
  );
4569
- const prevTransitionUuidRef = (0, import_react14.useRef)(transitionUuid);
4631
+ const prevTransitionUuidRef = (0, import_react15.useRef)(transitionUuid);
4570
4632
  if (prevTransitionUuidRef.current !== transitionUuid) {
4571
4633
  prevTransitionUuidRef.current = transitionUuid;
4572
4634
  setScheduleDelayDraft(
@@ -4581,7 +4643,7 @@ function TransitionForm({
4581
4643
  const handleRename = (next) => {
4582
4644
  if (next === transition.name) return;
4583
4645
  setRenameError(null);
4584
- if (!import_workflow_core6.NAME_REGEX.test(next)) {
4646
+ if (!import_workflow_core7.NAME_REGEX.test(next)) {
4585
4647
  setRenameError(`"${next}" is not a valid transition name`);
4586
4648
  return;
4587
4649
  }
@@ -4664,9 +4726,9 @@ function TransitionForm({
4664
4726
  index: index + 1
4665
4727
  });
4666
4728
  };
4667
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: transitionFormStyle, children: [
4668
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
4669
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4729
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: transitionFormStyle, children: [
4730
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(FieldGroup, { title: messages.inspector.properties, children: [
4731
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4670
4732
  TextField,
4671
4733
  {
4672
4734
  label: messages.inspector.name,
@@ -4677,8 +4739,8 @@ function TransitionForm({
4677
4739
  testId: "inspector-transition-name"
4678
4740
  }
4679
4741
  ),
4680
- renameError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4681
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4742
+ renameError && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { role: "alert", style: { color: colors.danger, fontSize: 12 }, children: renameError }),
4743
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4682
4744
  SelectField,
4683
4745
  {
4684
4746
  label: "Source state",
@@ -4698,7 +4760,7 @@ function TransitionForm({
4698
4760
  testId: "inspector-transition-source-state"
4699
4761
  }
4700
4762
  ),
4701
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4763
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4702
4764
  SelectField,
4703
4765
  {
4704
4766
  label: "Target state",
@@ -4709,7 +4771,7 @@ function TransitionForm({
4709
4771
  testId: "inspector-transition-next"
4710
4772
  }
4711
4773
  ),
4712
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4774
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4713
4775
  SelectField,
4714
4776
  {
4715
4777
  label: messages.inspector.transitionType,
@@ -4723,7 +4785,7 @@ function TransitionForm({
4723
4785
  testId: "inspector-transition-manual"
4724
4786
  }
4725
4787
  ),
4726
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4788
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4727
4789
  CheckboxField,
4728
4790
  {
4729
4791
  label: messages.inspector.disabled,
@@ -4733,7 +4795,7 @@ function TransitionForm({
4733
4795
  testId: "inspector-transition-disabled"
4734
4796
  }
4735
4797
  ),
4736
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4798
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4737
4799
  AnchorSelect,
4738
4800
  {
4739
4801
  label: messages.inspector.sourceAnchor,
@@ -4744,7 +4806,7 @@ function TransitionForm({
4744
4806
  testId: "inspector-transition-source-anchor"
4745
4807
  }
4746
4808
  ),
4747
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4809
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4748
4810
  AnchorSelect,
4749
4811
  {
4750
4812
  label: messages.inspector.targetAnchor,
@@ -4755,12 +4817,12 @@ function TransitionForm({
4755
4817
  testId: "inspector-transition-target-anchor"
4756
4818
  }
4757
4819
  ),
4758
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4759
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: 6 }, children: [
4760
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
4761
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
4820
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
4821
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 6 }, children: [
4822
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", disabled, onClick: () => reorder(-1), style: ghostBtn5, children: messages.inspector.moveUp }),
4823
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", disabled, onClick: () => reorder(1), style: ghostBtn5, children: messages.inspector.moveDown })
4762
4824
  ] }),
4763
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4825
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4764
4826
  "p",
4765
4827
  {
4766
4828
  style: {
@@ -4774,8 +4836,8 @@ function TransitionForm({
4774
4836
  }
4775
4837
  )
4776
4838
  ] }),
4777
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4778
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4839
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4840
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4779
4841
  "button",
4780
4842
  {
4781
4843
  type: "button",
@@ -4786,8 +4848,8 @@ function TransitionForm({
4786
4848
  children: "Delete transition"
4787
4849
  }
4788
4850
  ),
4789
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4790
- issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4851
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", { style: { border: "none", borderTop: `1px solid ${colors.borderSubtle}`, margin: 0 } }),
4852
+ issues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4791
4853
  "div",
4792
4854
  {
4793
4855
  role: "alert",
@@ -4804,12 +4866,12 @@ function TransitionForm({
4804
4866
  `${issue.code}-${i}`
4805
4867
  )) })
4806
4868
  ] }),
4807
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4869
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4808
4870
  TransitionSection,
4809
4871
  {
4810
4872
  title: messages.inspector.criteria,
4811
4873
  testId: "inspector-transition-criteria-section",
4812
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4874
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4813
4875
  CriterionSection,
4814
4876
  {
4815
4877
  host,
@@ -4825,18 +4887,18 @@ function TransitionForm({
4825
4887
  )
4826
4888
  }
4827
4889
  ),
4828
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4890
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4829
4891
  TransitionSection,
4830
4892
  {
4831
4893
  title: "Scheduled transition",
4832
4894
  testId: "inspector-transition-schedule-section",
4833
4895
  children: [
4834
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4896
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4835
4897
  "label",
4836
4898
  {
4837
4899
  style: { display: "flex", flexDirection: "row", alignItems: "center", gap: 8, fontSize: 12, color: colors.textSecondary, cursor: "pointer" },
4838
4900
  children: [
4839
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4901
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4840
4902
  "input",
4841
4903
  {
4842
4904
  type: "checkbox",
@@ -4856,14 +4918,14 @@ function TransitionForm({
4856
4918
  }
4857
4919
  }
4858
4920
  ),
4859
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Enable schedule" })
4921
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Enable schedule" })
4860
4922
  ]
4861
4923
  }
4862
4924
  ),
4863
- transition.schedule !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4864
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4865
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
4866
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4925
+ transition.schedule !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
4926
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4927
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: "Delay (ms)" }),
4928
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4867
4929
  "input",
4868
4930
  {
4869
4931
  type: "text",
@@ -4879,9 +4941,9 @@ function TransitionForm({
4879
4941
  }
4880
4942
  )
4881
4943
  ] }),
4882
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4883
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
4884
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4944
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
4945
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: "Timeout (ms)" }),
4946
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4885
4947
  "input",
4886
4948
  {
4887
4949
  type: "text",
@@ -4898,7 +4960,7 @@ function TransitionForm({
4898
4960
  )
4899
4961
  ] })
4900
4962
  ] }),
4901
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4963
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4902
4964
  "p",
4903
4965
  {
4904
4966
  style: {
@@ -4918,28 +4980,28 @@ function TransitionForm({
4918
4980
  ]
4919
4981
  }
4920
4982
  ),
4921
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4983
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4922
4984
  TransitionSection,
4923
4985
  {
4924
4986
  title: messages.inspector.processors,
4925
4987
  testId: "inspector-transition-processes-section",
4926
4988
  children: [
4927
- processorCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4928
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
4929
- processors.map((processor, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: processorRowStyle, children: [
4930
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
4931
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { style: processorOrderStyle, children: [
4989
+ processorCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: emptyProcessorStateStyle, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: summaryTextStyle2, children: "No processors run on this transition." }) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
4990
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: processorHelperStyle, children: "Processors run sequentially in the order shown." }),
4991
+ processors.map((processor, index) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: processorRowStyle, children: [
4992
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
4993
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { style: processorOrderStyle, children: [
4932
4994
  index + 1,
4933
4995
  "."
4934
4996
  ] }),
4935
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: processorTypeChipStyle, children: processor.type }),
4936
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
4937
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
4938
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
4997
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: processorTypeChipStyle, children: processor.type }),
4998
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }, children: [
4999
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { style: { fontSize: 13 }, children: processor.name }),
5000
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: summaryTextStyle2, children: summarizeProcessor(processor) })
4939
5001
  ] })
4940
5002
  ] }),
4941
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
4942
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5003
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
5004
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4943
5005
  "button",
4944
5006
  {
4945
5007
  type: "button",
@@ -4954,7 +5016,7 @@ function TransitionForm({
4954
5016
  children: "Edit"
4955
5017
  }
4956
5018
  ),
4957
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5019
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4958
5020
  "button",
4959
5021
  {
4960
5022
  type: "button",
@@ -4965,7 +5027,7 @@ function TransitionForm({
4965
5027
  children: "Duplicate"
4966
5028
  }
4967
5029
  ),
4968
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5030
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4969
5031
  "button",
4970
5032
  {
4971
5033
  type: "button",
@@ -4981,7 +5043,7 @@ function TransitionForm({
4981
5043
  children: "Move up"
4982
5044
  }
4983
5045
  ),
4984
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5046
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4985
5047
  "button",
4986
5048
  {
4987
5049
  type: "button",
@@ -4997,7 +5059,7 @@ function TransitionForm({
4997
5059
  children: "Move down"
4998
5060
  }
4999
5061
  ),
5000
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5062
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5001
5063
  "button",
5002
5064
  {
5003
5065
  type: "button",
@@ -5011,7 +5073,7 @@ function TransitionForm({
5011
5073
  ] })
5012
5074
  ] }, processorUuids[index] ?? `${processor.name}-${index}`))
5013
5075
  ] }),
5014
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5076
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5015
5077
  "button",
5016
5078
  {
5017
5079
  type: "button",
@@ -5025,7 +5087,18 @@ function TransitionForm({
5025
5087
  ]
5026
5088
  }
5027
5089
  ),
5028
- processorModal && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5090
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TransitionSection, { title: "Annotations", testId: "inspector-transition-annotations-section", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5091
+ AnnotationsField,
5092
+ {
5093
+ value: transition.annotations,
5094
+ disabled,
5095
+ showLabel: false,
5096
+ modelKey: `transition-${transitionUuid}`,
5097
+ onCommit: (annotations) => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid }, annotations }),
5098
+ onRemove: () => onDispatch({ op: "setAnnotations", target: { kind: "transition", transitionUuid } })
5099
+ }
5100
+ ) }),
5101
+ processorModal && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5029
5102
  ProcessorEditorModal,
5030
5103
  {
5031
5104
  title: processorModal.mode === "add" ? "Add processor" : "Edit processor",
@@ -5045,8 +5118,8 @@ function TransitionSection({
5045
5118
  testId,
5046
5119
  children
5047
5120
  }) {
5048
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5049
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("header", { style: sectionHeaderStyle, children: title }),
5121
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("section", { style: transitionSectionStyle, "data-testid": testId, children: [
5122
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("header", { style: sectionHeaderStyle, children: title }),
5050
5123
  children
5051
5124
  ] });
5052
5125
  }
@@ -5153,9 +5226,9 @@ function AnchorSelect({
5153
5226
  { value: "left", label: messages.inspector.anchorLeft },
5154
5227
  { value: "left-bottom", label: messages.inspector.anchorLeftBottom }
5155
5228
  ];
5156
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5157
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontWeight: 500 }, children: label }),
5158
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5229
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4, fontSize: 12, color: colors.textSecondary }, children: [
5230
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: 500 }, children: label }),
5231
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5159
5232
  CustomSelectInput,
5160
5233
  {
5161
5234
  value: value ?? "",
@@ -5170,7 +5243,7 @@ function AnchorSelect({
5170
5243
  }
5171
5244
 
5172
5245
  // src/inspector/Inspector.tsx
5173
- var import_jsx_runtime14 = require("react/jsx-runtime");
5246
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5174
5247
  function issueKeyForSelection(selection) {
5175
5248
  if (!selection) return null;
5176
5249
  switch (selection.kind) {
@@ -5195,20 +5268,22 @@ function Inspector({
5195
5268
  onSelectionChange,
5196
5269
  onClose,
5197
5270
  onRequestDeleteState,
5198
- width = 384
5271
+ docked,
5272
+ onToggleDock,
5273
+ onMinimize
5199
5274
  }) {
5200
5275
  const messages = useMessages();
5201
5276
  const { developerMode } = useEditorConfig();
5202
- const [tab, setTab] = (0, import_react15.useState)("properties");
5277
+ const [tab, setTab] = (0, import_react16.useState)("properties");
5203
5278
  const effectiveTab = developerMode ? tab : "properties";
5204
- const resolved = (0, import_react15.useMemo)(() => resolveSelection(doc, selection), [doc, selection]);
5279
+ const resolved = (0, import_react16.useMemo)(() => resolveSelection(doc, selection), [doc, selection]);
5205
5280
  const selectionIssueKey = issueKeyForSelection(selection);
5206
- const selectionIssues = (0, import_react15.useMemo)(() => {
5281
+ const selectionIssues = (0, import_react16.useMemo)(() => {
5207
5282
  if (!selectionIssueKey) return [];
5208
5283
  return issues.filter((i) => i.targetId === selectionIssueKey);
5209
5284
  }, [issues, selectionIssueKey]);
5210
5285
  const breadcrumb = renderBreadcrumb(resolved);
5211
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5286
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5212
5287
  "aside",
5213
5288
  {
5214
5289
  style: {
@@ -5217,16 +5292,17 @@ function Inspector({
5217
5292
  flexDirection: "column",
5218
5293
  background: colors.surfaceMuted,
5219
5294
  borderLeft: `1px solid ${colors.borderSubtle}`,
5220
- flex: `0 0 ${width}px`,
5221
- width,
5222
- minWidth: 360,
5295
+ flex: "1 1 auto",
5296
+ width: "100%",
5297
+ minWidth: 0,
5223
5298
  fontFamily: fonts.sans
5224
5299
  },
5225
5300
  "data-testid": "inspector",
5226
5301
  children: [
5227
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5302
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5228
5303
  "header",
5229
5304
  {
5305
+ "data-inspector-drag-handle": true,
5230
5306
  style: {
5231
5307
  padding: "10px 12px",
5232
5308
  borderBottom: `1px solid ${colors.borderSubtle}`,
@@ -5237,8 +5313,59 @@ function Inspector({
5237
5313
  gap: 8
5238
5314
  },
5239
5315
  children: [
5240
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5241
- onClose && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5316
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: breadcrumb }),
5317
+ onToggleDock && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5318
+ "button",
5319
+ {
5320
+ type: "button",
5321
+ "aria-label": docked ? messages.inspector.detachPanel : messages.inspector.dockPanel,
5322
+ title: docked ? messages.inspector.detachPanel : messages.inspector.dockPanel,
5323
+ "data-testid": "inspector-dock-toggle",
5324
+ onClick: onToggleDock,
5325
+ style: {
5326
+ width: 24,
5327
+ height: 24,
5328
+ border: `1px solid ${colors.border}`,
5329
+ borderRadius: radii.sm,
5330
+ background: "white",
5331
+ color: colors.textSecondary,
5332
+ cursor: "pointer",
5333
+ display: "inline-flex",
5334
+ alignItems: "center",
5335
+ justifyContent: "center",
5336
+ padding: 0,
5337
+ fontSize: 13
5338
+ },
5339
+ children: docked ? "\u2922" : "\u2921"
5340
+ }
5341
+ ),
5342
+ onMinimize && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5343
+ "button",
5344
+ {
5345
+ type: "button",
5346
+ "aria-label": messages.inspector.minimize,
5347
+ title: messages.inspector.minimize,
5348
+ "data-testid": "inspector-minimize",
5349
+ onClick: onMinimize,
5350
+ style: {
5351
+ width: 24,
5352
+ height: 24,
5353
+ border: `1px solid ${colors.border}`,
5354
+ borderRadius: radii.sm,
5355
+ background: "white",
5356
+ color: colors.textSecondary,
5357
+ cursor: "pointer",
5358
+ display: "inline-flex",
5359
+ alignItems: "flex-end",
5360
+ justifyContent: "center",
5361
+ padding: "0 0 5px",
5362
+ fontSize: 18,
5363
+ lineHeight: "10px"
5364
+ },
5365
+ children: "\u2013"
5366
+ }
5367
+ ),
5368
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5242
5369
  "button",
5243
5370
  {
5244
5371
  type: "button",
@@ -5266,8 +5393,8 @@ function Inspector({
5266
5393
  ]
5267
5394
  }
5268
5395
  ),
5269
- developerMode && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5270
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5396
+ developerMode && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { display: "flex", borderBottom: `1px solid ${colors.borderSubtle}` }, children: [
5397
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5271
5398
  TabButton,
5272
5399
  {
5273
5400
  active: effectiveTab === "properties",
@@ -5276,7 +5403,7 @@ function Inspector({
5276
5403
  children: messages.inspector.properties
5277
5404
  }
5278
5405
  ),
5279
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5406
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5280
5407
  TabButton,
5281
5408
  {
5282
5409
  active: effectiveTab === "json",
@@ -5286,11 +5413,11 @@ function Inspector({
5286
5413
  }
5287
5414
  )
5288
5415
  ] }),
5289
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5290
- effectiveTab === "properties" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
5291
- !resolved && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(EmptyState, { message: messages.inspector.empty }),
5292
- resolved?.kind === "workflow" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5293
- resolved?.kind === "state" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5416
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { padding: 12, overflowY: "auto", flex: 1, display: "flex", flexDirection: "column", gap: 16 }, children: [
5417
+ effectiveTab === "properties" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
5418
+ !resolved && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(EmptyState, { message: messages.inspector.empty }),
5419
+ resolved?.kind === "workflow" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(WorkflowForm, { workflow: resolved.workflow, disabled: readOnly, onDispatch }, resolved.workflow.name),
5420
+ resolved?.kind === "state" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5294
5421
  StateForm,
5295
5422
  {
5296
5423
  workflow: resolved.workflow,
@@ -5303,7 +5430,7 @@ function Inspector({
5303
5430
  },
5304
5431
  `${resolved.workflow.name}:${resolved.stateCode}`
5305
5432
  ),
5306
- resolved?.kind === "transition" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5433
+ resolved?.kind === "transition" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5307
5434
  TransitionForm,
5308
5435
  {
5309
5436
  workflow: resolved.workflow,
@@ -5320,7 +5447,7 @@ function Inspector({
5320
5447
  },
5321
5448
  resolved.transitionUuid
5322
5449
  ),
5323
- resolved?.kind === "processor" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5450
+ resolved?.kind === "processor" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5324
5451
  ProcessorForm,
5325
5452
  {
5326
5453
  processor: resolved.processor,
@@ -5334,8 +5461,8 @@ function Inspector({
5334
5461
  resolved.processorUuid
5335
5462
  )
5336
5463
  ] }),
5337
- developerMode && effectiveTab === "json" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(JsonPreview, { document: doc, resolved }),
5338
- selectionIssues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5464
+ developerMode && effectiveTab === "json" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(JsonPreview, { document: doc, resolved }),
5465
+ selectionIssues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IssuesList, { issues: selectionIssues, title: messages.inspector.issues })
5339
5466
  ] })
5340
5467
  ]
5341
5468
  }
@@ -5358,7 +5485,7 @@ function TabButton({
5358
5485
  children,
5359
5486
  testId
5360
5487
  }) {
5361
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5488
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5362
5489
  "button",
5363
5490
  {
5364
5491
  type: "button",
@@ -5379,17 +5506,17 @@ function TabButton({
5379
5506
  );
5380
5507
  }
5381
5508
  function EmptyState({ message }) {
5382
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5509
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: { color: colors.textTertiary, fontSize: 13 }, children: message });
5383
5510
  }
5384
5511
  function IssuesList({
5385
5512
  issues,
5386
5513
  title
5387
5514
  }) {
5388
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5389
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5515
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
5516
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("header", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: colors.textSecondary }, children: title }),
5390
5517
  issues.map((issue, i) => {
5391
5518
  const tone = severityTone(issue.severity);
5392
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5519
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5393
5520
  "div",
5394
5521
  {
5395
5522
  style: {
@@ -5400,8 +5527,8 @@ function IssuesList({
5400
5527
  fontSize: 12
5401
5528
  },
5402
5529
  children: [
5403
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: issue.code }),
5404
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: issue.message })
5530
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: issue.code }),
5531
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: issue.message })
5405
5532
  ]
5406
5533
  },
5407
5534
  `${issue.code}-${i}`
@@ -5413,15 +5540,15 @@ function JsonPreview({
5413
5540
  document: doc,
5414
5541
  resolved
5415
5542
  }) {
5416
- const json = (0, import_react15.useMemo)(() => {
5417
- if (!resolved) return (0, import_workflow_core7.serializeEditorDocument)(doc);
5543
+ const json = (0, import_react16.useMemo)(() => {
5544
+ if (!resolved) return (0, import_workflow_core8.serializeEditorDocument)(doc);
5418
5545
  if (resolved.kind === "workflow") return JSON.stringify(resolved.workflow, null, 2);
5419
5546
  if (resolved.kind === "state") return JSON.stringify(resolved.state, null, 2);
5420
5547
  if (resolved.kind === "transition") return JSON.stringify(resolved.transition, null, 2);
5421
5548
  if (resolved.kind === "processor") return JSON.stringify(resolved.processor, null, 2);
5422
5549
  return "";
5423
5550
  }, [doc, resolved]);
5424
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5551
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5425
5552
  "pre",
5426
5553
  {
5427
5554
  style: {
@@ -5443,8 +5570,221 @@ function JsonPreview({
5443
5570
  );
5444
5571
  }
5445
5572
 
5573
+ // src/inspector/inspectorPlacement.ts
5574
+ var MIN_FLOAT_W = 340;
5575
+ var MIN_FLOAT_H = 260;
5576
+ function clampRect(rect, viewport) {
5577
+ const width = Math.min(Math.max(rect.width, MIN_FLOAT_W), viewport.w);
5578
+ const height = Math.min(Math.max(rect.height, MIN_FLOAT_H), viewport.h);
5579
+ const left = Math.min(Math.max(rect.left, 0), Math.max(0, viewport.w - width));
5580
+ const top = Math.min(Math.max(rect.top, 0), Math.max(0, viewport.h - height));
5581
+ return { left, top, width, height };
5582
+ }
5583
+ function placementStorageKey(base) {
5584
+ return `${base}:inspector`;
5585
+ }
5586
+ function loadPlacement(base) {
5587
+ if (base === null) return null;
5588
+ try {
5589
+ const raw = localStorage.getItem(placementStorageKey(base));
5590
+ if (!raw) return null;
5591
+ const p = JSON.parse(raw);
5592
+ 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") {
5593
+ return p;
5594
+ }
5595
+ return null;
5596
+ } catch {
5597
+ return null;
5598
+ }
5599
+ }
5600
+ function savePlacement(base, p) {
5601
+ if (base === null) return;
5602
+ try {
5603
+ localStorage.setItem(placementStorageKey(base), JSON.stringify(p));
5604
+ } catch {
5605
+ }
5606
+ }
5607
+
5608
+ // src/inspector/InspectorFrame.tsx
5609
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5610
+ var FLOATING_Z = 40;
5611
+ var MIN_BAR_Z = 50;
5612
+ function InspectorFrame({
5613
+ mode,
5614
+ rect,
5615
+ dockedWidth,
5616
+ onRectChange,
5617
+ onDockedWidthChange,
5618
+ onRestore,
5619
+ onClose,
5620
+ children
5621
+ }) {
5622
+ const messages = useMessages();
5623
+ const startWidthDrag = (e) => {
5624
+ e.preventDefault();
5625
+ const startX = e.clientX;
5626
+ const startW = dockedWidth;
5627
+ const onMove = (ev) => onDockedWidthChange(Math.max(360, startW + (startX - ev.clientX)));
5628
+ const onUp = () => {
5629
+ document.removeEventListener("mousemove", onMove);
5630
+ document.removeEventListener("mouseup", onUp);
5631
+ };
5632
+ document.addEventListener("mousemove", onMove);
5633
+ document.addEventListener("mouseup", onUp);
5634
+ };
5635
+ const viewport = () => ({ w: window.innerWidth, h: window.innerHeight });
5636
+ const startMove = (e) => {
5637
+ const target = e.target;
5638
+ if (target.closest("button")) return;
5639
+ if (!target.closest("[data-inspector-drag-handle]")) return;
5640
+ e.preventDefault();
5641
+ const dx = e.clientX - rect.left;
5642
+ const dy = e.clientY - rect.top;
5643
+ const onMove = (ev) => onRectChange(clampRect({ ...rect, left: ev.clientX - dx, top: ev.clientY - dy }, viewport()));
5644
+ const onUp = () => {
5645
+ document.removeEventListener("mousemove", onMove);
5646
+ document.removeEventListener("mouseup", onUp);
5647
+ };
5648
+ document.addEventListener("mousemove", onMove);
5649
+ document.addEventListener("mouseup", onUp);
5650
+ };
5651
+ const startResize = (e) => {
5652
+ e.preventDefault();
5653
+ e.stopPropagation();
5654
+ const sx = e.clientX, sy = e.clientY, sw = rect.width, sh = rect.height;
5655
+ 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()));
5656
+ const onUp = () => {
5657
+ document.removeEventListener("mousemove", onMove);
5658
+ document.removeEventListener("mouseup", onUp);
5659
+ };
5660
+ document.addEventListener("mousemove", onMove);
5661
+ document.addEventListener("mouseup", onUp);
5662
+ };
5663
+ const floating = mode === "floating";
5664
+ const minimized = mode === "minimized";
5665
+ const style = floating || minimized ? {
5666
+ position: "fixed",
5667
+ left: rect.left,
5668
+ top: rect.top,
5669
+ width: rect.width,
5670
+ height: rect.height,
5671
+ zIndex: FLOATING_Z,
5672
+ boxShadow: "0 24px 50px -12px rgba(15,23,42,0.45)",
5673
+ borderRadius: 12,
5674
+ overflow: "hidden",
5675
+ display: minimized ? "none" : "flex"
5676
+ } : { position: "relative", flex: `0 0 ${dockedWidth}px`, width: dockedWidth, height: "100%", display: "flex" };
5677
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
5678
+ mode === "docked" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5679
+ "div",
5680
+ {
5681
+ "data-testid": "inspector-resize-handle",
5682
+ onMouseDown: startWidthDrag,
5683
+ style: { width: 3, flexShrink: 0, cursor: "col-resize", background: "transparent", borderLeft: `1px solid ${colors.borderSubtle}`, zIndex: 10 },
5684
+ onMouseEnter: (e) => e.currentTarget.style.background = colors.border,
5685
+ onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
5686
+ }
5687
+ ),
5688
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5689
+ "div",
5690
+ {
5691
+ "data-testid": "inspector-frame",
5692
+ onMouseDownCapture: floating ? startMove : void 0,
5693
+ style,
5694
+ children: [
5695
+ children,
5696
+ floating && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5697
+ "div",
5698
+ {
5699
+ "data-testid": "inspector-resize-grip",
5700
+ onMouseDown: startResize,
5701
+ style: { position: "absolute", right: 2, bottom: 2, width: 16, height: 16, cursor: "nwse-resize", zIndex: 5 }
5702
+ }
5703
+ )
5704
+ ]
5705
+ }
5706
+ ),
5707
+ minimized && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5708
+ "div",
5709
+ {
5710
+ "data-testid": "inspector-min-bar",
5711
+ onClick: onRestore,
5712
+ title: messages.inspector.restore,
5713
+ style: minBarStyle,
5714
+ children: [
5715
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { width: 8, height: 8, borderRadius: "50%", background: colors.primary, flex: "0 0 auto" } }),
5716
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12, color: colors.textSecondary }, children: messages.inspector.minimizedTitle }),
5717
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5718
+ "button",
5719
+ {
5720
+ type: "button",
5721
+ "data-testid": "inspector-restore",
5722
+ "aria-label": messages.inspector.restore,
5723
+ title: messages.inspector.restore,
5724
+ onClick: (e) => {
5725
+ e.stopPropagation();
5726
+ onRestore();
5727
+ },
5728
+ style: barBtnStyle,
5729
+ children: "\u2922"
5730
+ }
5731
+ ),
5732
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5733
+ "button",
5734
+ {
5735
+ type: "button",
5736
+ "data-testid": "inspector-min-close",
5737
+ "aria-label": "Close inspector",
5738
+ title: "Close inspector",
5739
+ onClick: (e) => {
5740
+ e.stopPropagation();
5741
+ onClose();
5742
+ },
5743
+ style: { ...barBtnStyle, fontSize: 16 },
5744
+ children: "\xD7"
5745
+ }
5746
+ )
5747
+ ]
5748
+ }
5749
+ )
5750
+ ] });
5751
+ }
5752
+ var minBarStyle = {
5753
+ position: "fixed",
5754
+ right: 16,
5755
+ bottom: 16,
5756
+ zIndex: MIN_BAR_Z,
5757
+ display: "flex",
5758
+ alignItems: "center",
5759
+ gap: 8,
5760
+ width: 260,
5761
+ height: 40,
5762
+ padding: "0 6px 0 12px",
5763
+ borderRadius: 10,
5764
+ background: "white",
5765
+ border: `1px solid ${colors.border}`,
5766
+ boxShadow: "0 12px 28px -10px rgba(15,23,42,0.4)",
5767
+ cursor: "pointer",
5768
+ userSelect: "none"
5769
+ };
5770
+ var barBtnStyle = {
5771
+ width: 24,
5772
+ height: 24,
5773
+ flex: "0 0 auto",
5774
+ border: `1px solid ${colors.border}`,
5775
+ borderRadius: radii.sm,
5776
+ background: "white",
5777
+ color: colors.textSecondary,
5778
+ cursor: "pointer",
5779
+ display: "inline-flex",
5780
+ alignItems: "center",
5781
+ justifyContent: "center",
5782
+ padding: 0,
5783
+ fontSize: 13
5784
+ };
5785
+
5446
5786
  // src/toolbar/Toolbar.tsx
5447
- var import_jsx_runtime15 = require("react/jsx-runtime");
5787
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5448
5788
  function Toolbar({
5449
5789
  derived,
5450
5790
  readOnly,
@@ -5458,7 +5798,7 @@ function Toolbar({
5458
5798
  toolbarEnd
5459
5799
  }) {
5460
5800
  const messages = useMessages();
5461
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5801
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5462
5802
  "footer",
5463
5803
  {
5464
5804
  style: {
@@ -5473,11 +5813,11 @@ function Toolbar({
5473
5813
  },
5474
5814
  "data-testid": "toolbar",
5475
5815
  children: [
5476
- toolbarStart && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
5477
- toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
5478
- !toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { flex: 1 } }),
5479
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
5480
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5816
+ toolbarStart && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: slotStyle, "data-testid": "toolbar-start", children: toolbarStart }),
5817
+ toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { ...slotStyle, flex: 1, justifyContent: "center" }, "data-testid": "toolbar-center", children: toolbarCenter }),
5818
+ !toolbarCenter && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { flex: 1 } }),
5819
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { role: "status", "aria-live": "polite", style: { display: "inline-flex", gap: 6 }, children: [
5820
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5481
5821
  ValidationPill,
5482
5822
  {
5483
5823
  severity: "error",
@@ -5489,7 +5829,7 @@ function Toolbar({
5489
5829
  testId: "toolbar-errors"
5490
5830
  }
5491
5831
  ),
5492
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5832
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5493
5833
  ValidationPill,
5494
5834
  {
5495
5835
  severity: "warning",
@@ -5501,7 +5841,7 @@ function Toolbar({
5501
5841
  testId: "toolbar-warnings"
5502
5842
  }
5503
5843
  ),
5504
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5844
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5505
5845
  ValidationPill,
5506
5846
  {
5507
5847
  severity: "info",
@@ -5514,7 +5854,7 @@ function Toolbar({
5514
5854
  }
5515
5855
  )
5516
5856
  ] }),
5517
- onSave && showSaveButton && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5857
+ onSave && showSaveButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5518
5858
  "button",
5519
5859
  {
5520
5860
  type: "button",
@@ -5525,7 +5865,7 @@ function Toolbar({
5525
5865
  children: messages.toolbar.save
5526
5866
  }
5527
5867
  ),
5528
- toolbarEnd && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5868
+ toolbarEnd && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: slotStyle, "data-testid": "toolbar-end", children: toolbarEnd })
5529
5869
  ]
5530
5870
  }
5531
5871
  );
@@ -5547,7 +5887,7 @@ function ValidationPill({
5547
5887
  const tone = severityTone(severity);
5548
5888
  const interactive = count > 0 && !!onClick;
5549
5889
  const hasIssues = count > 0;
5550
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5890
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5551
5891
  "button",
5552
5892
  {
5553
5893
  type: "button",
@@ -5574,7 +5914,7 @@ function ValidationPill({
5574
5914
  height: 20
5575
5915
  },
5576
5916
  children: [
5577
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5917
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { fontSize: severity === "info" ? 14 : 10, lineHeight: 1 }, children: SEVERITY_ICON[severity] }),
5578
5918
  count
5579
5919
  ]
5580
5920
  }
@@ -5598,8 +5938,8 @@ var slotStyle = {
5598
5938
  };
5599
5939
 
5600
5940
  // src/toolbar/IssuesDrawer.tsx
5601
- var import_react16 = require("react");
5602
- var import_jsx_runtime16 = require("react/jsx-runtime");
5941
+ var import_react17 = require("react");
5942
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5603
5943
  function resolveTarget(doc, targetId) {
5604
5944
  if (!targetId) return null;
5605
5945
  const ids = doc.meta.ids;
@@ -5652,8 +5992,8 @@ function IssuesDrawer({
5652
5992
  onJumpTo
5653
5993
  }) {
5654
5994
  const messages = useMessages();
5655
- const ref = (0, import_react16.useRef)(null);
5656
- (0, import_react16.useEffect)(() => {
5995
+ const ref = (0, import_react17.useRef)(null);
5996
+ (0, import_react17.useEffect)(() => {
5657
5997
  if (!open) return;
5658
5998
  function onKey(e) {
5659
5999
  if (e.key === "Escape") {
@@ -5677,18 +6017,18 @@ function IssuesDrawer({
5677
6017
  window.removeEventListener("mousedown", onClick);
5678
6018
  };
5679
6019
  }, [open, onClose]);
5680
- const filtered = (0, import_react16.useMemo)(
6020
+ const filtered = (0, import_react17.useMemo)(
5681
6021
  () => issues.filter((i) => i.severity === severity),
5682
6022
  [issues, severity]
5683
6023
  );
5684
- const title = (0, import_react16.useMemo)(() => {
6024
+ const title = (0, import_react17.useMemo)(() => {
5685
6025
  if (severity === "error") return messages.issues.errors;
5686
6026
  if (severity === "warning") return messages.issues.warnings;
5687
6027
  return messages.issues.infos;
5688
6028
  }, [severity, messages]);
5689
6029
  const tone = severityTone(severity);
5690
6030
  if (!open) return null;
5691
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6031
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5692
6032
  "div",
5693
6033
  {
5694
6034
  ref,
@@ -5712,7 +6052,7 @@ function IssuesDrawer({
5712
6052
  flexDirection: "column"
5713
6053
  },
5714
6054
  children: [
5715
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6055
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5716
6056
  "header",
5717
6057
  {
5718
6058
  style: {
@@ -5723,7 +6063,7 @@ function IssuesDrawer({
5723
6063
  gap: 8
5724
6064
  },
5725
6065
  children: [
5726
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6066
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5727
6067
  "span",
5728
6068
  {
5729
6069
  style: {
@@ -5736,12 +6076,12 @@ function IssuesDrawer({
5736
6076
  "aria-hidden": true
5737
6077
  }
5738
6078
  ),
5739
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
6079
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("strong", { style: { flex: 1, fontSize: 13, color: colors.textPrimary }, children: [
5740
6080
  title,
5741
6081
  " \xB7 ",
5742
6082
  filtered.length
5743
6083
  ] }),
5744
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6084
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5745
6085
  "button",
5746
6086
  {
5747
6087
  type: "button",
@@ -5764,14 +6104,14 @@ function IssuesDrawer({
5764
6104
  ]
5765
6105
  }
5766
6106
  ),
5767
- filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6107
+ filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5768
6108
  "p",
5769
6109
  {
5770
6110
  style: { padding: 12, color: colors.textTertiary, fontSize: 12, margin: 0 },
5771
6111
  "data-testid": "issues-drawer-empty",
5772
6112
  children: messages.issues.none
5773
6113
  }
5774
- ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6114
+ ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5775
6115
  "ul",
5776
6116
  {
5777
6117
  style: {
@@ -5785,7 +6125,7 @@ function IssuesDrawer({
5785
6125
  children: filtered.map((issue, idx) => {
5786
6126
  const target = resolveTarget(doc, issue.targetId);
5787
6127
  const targetLabel = target ? target.kind === "transition" ? `${messages.issues.relatedTransition}: ${target.label}` : target.kind === "state" ? `${messages.issues.relatedState}: ${target.label}` : target.label : null;
5788
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6128
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5789
6129
  "li",
5790
6130
  {
5791
6131
  style: {
@@ -5799,10 +6139,10 @@ function IssuesDrawer({
5799
6139
  },
5800
6140
  "data-testid": `issues-drawer-item-${idx}`,
5801
6141
  children: [
5802
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
5803
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
5804
- targetLabel && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
5805
- target && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6142
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 11, fontWeight: 700, color: tone.fg }, children: issue.code }),
6143
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 12, color: colors.textPrimary }, children: issue.message }),
6144
+ targetLabel && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { fontSize: 11, color: colors.textSecondary }, children: targetLabel }),
6145
+ target && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5806
6146
  "button",
5807
6147
  {
5808
6148
  type: "button",
@@ -5837,23 +6177,23 @@ function IssuesDrawer({
5837
6177
  }
5838
6178
 
5839
6179
  // src/toolbar/WorkflowTabs.tsx
5840
- var import_react18 = require("react");
6180
+ var import_react19 = require("react");
5841
6181
 
5842
6182
  // src/toolbar/VersionBadge.tsx
5843
- var import_react17 = require("react");
6183
+ var import_react18 = require("react");
5844
6184
  var import_react_dom2 = require("react-dom");
5845
- var import_jsx_runtime17 = require("react/jsx-runtime");
6185
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5846
6186
  function VersionBadge({
5847
6187
  version,
5848
6188
  supportedVersions,
5849
6189
  readOnly = false,
5850
6190
  onVersionChange
5851
6191
  }) {
5852
- const [open, setOpen] = (0, import_react17.useState)(false);
5853
- const [dropdownPos, setDropdownPos] = (0, import_react17.useState)(null);
5854
- const buttonRef = (0, import_react17.useRef)(null);
5855
- const dropdownRef = (0, import_react17.useRef)(null);
5856
- (0, import_react17.useEffect)(() => {
6192
+ const [open, setOpen] = (0, import_react18.useState)(false);
6193
+ const [dropdownPos, setDropdownPos] = (0, import_react18.useState)(null);
6194
+ const buttonRef = (0, import_react18.useRef)(null);
6195
+ const dropdownRef = (0, import_react18.useRef)(null);
6196
+ (0, import_react18.useEffect)(() => {
5857
6197
  if (!open) return;
5858
6198
  const handler = (e) => {
5859
6199
  const target = e.target;
@@ -5875,7 +6215,7 @@ function VersionBadge({
5875
6215
  setOpen((o) => !o);
5876
6216
  };
5877
6217
  if (readOnly) {
5878
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6218
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5879
6219
  "div",
5880
6220
  {
5881
6221
  "data-testid": "version-badge",
@@ -5894,7 +6234,7 @@ function VersionBadge({
5894
6234
  );
5895
6235
  }
5896
6236
  const dropdown = open && dropdownPos ? (0, import_react_dom2.createPortal)(
5897
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
6237
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5898
6238
  "div",
5899
6239
  {
5900
6240
  ref: dropdownRef,
@@ -5913,7 +6253,7 @@ function VersionBadge({
5913
6253
  zIndex: 9999
5914
6254
  },
5915
6255
  children: [
5916
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6256
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5917
6257
  "div",
5918
6258
  {
5919
6259
  style: {
@@ -5930,7 +6270,7 @@ function VersionBadge({
5930
6270
  ),
5931
6271
  [...supportedVersions].reverse().map((v) => {
5932
6272
  const isCurrent = v === version.replace(/^v/, "");
5933
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
6273
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5934
6274
  "button",
5935
6275
  {
5936
6276
  type: "button",
@@ -5953,16 +6293,16 @@ function VersionBadge({
5953
6293
  textAlign: "left"
5954
6294
  },
5955
6295
  children: [
5956
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
6296
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { children: [
5957
6297
  v,
5958
6298
  " ",
5959
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
6299
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 11, color: isCurrent ? "#93C5FD" : "#94A3B8" }, children: [
5960
6300
  "cyoda-go ",
5961
6301
  v,
5962
6302
  ".x"
5963
6303
  ] })
5964
6304
  ] }),
5965
- isCurrent && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6305
+ isCurrent && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5966
6306
  "span",
5967
6307
  {
5968
6308
  style: {
@@ -5986,8 +6326,8 @@ function VersionBadge({
5986
6326
  ),
5987
6327
  document.body
5988
6328
  ) : null;
5989
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
5990
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
6329
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6330
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5991
6331
  "button",
5992
6332
  {
5993
6333
  ref: buttonRef,
@@ -6010,7 +6350,7 @@ function VersionBadge({
6010
6350
  },
6011
6351
  children: [
6012
6352
  version,
6013
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6353
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 10, opacity: 0.7 }, children: open ? "\u25B4" : "\u25BE" })
6014
6354
  ]
6015
6355
  }
6016
6356
  ),
@@ -6019,7 +6359,7 @@ function VersionBadge({
6019
6359
  }
6020
6360
 
6021
6361
  // src/toolbar/WorkflowTabs.tsx
6022
- var import_jsx_runtime18 = require("react/jsx-runtime");
6362
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6023
6363
  function WorkflowTabs({
6024
6364
  workflows,
6025
6365
  activeWorkflow,
@@ -6033,10 +6373,10 @@ function WorkflowTabs({
6033
6373
  onVersionChange
6034
6374
  }) {
6035
6375
  const messages = useMessages();
6036
- const [editingTab, setEditingTab] = (0, import_react18.useState)(null);
6037
- const [draftName, setDraftName] = (0, import_react18.useState)("");
6038
- const inputRef = (0, import_react18.useRef)(null);
6039
- (0, import_react18.useEffect)(() => {
6376
+ const [editingTab, setEditingTab] = (0, import_react19.useState)(null);
6377
+ const [draftName, setDraftName] = (0, import_react19.useState)("");
6378
+ const inputRef = (0, import_react19.useRef)(null);
6379
+ (0, import_react19.useEffect)(() => {
6040
6380
  if (editingTab !== null) inputRef.current?.select();
6041
6381
  }, [editingTab]);
6042
6382
  const startEditing = (name) => {
@@ -6056,7 +6396,7 @@ function WorkflowTabs({
6056
6396
  setEditingTab(null);
6057
6397
  };
6058
6398
  const cancelEdit = () => setEditingTab(null);
6059
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
6399
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6060
6400
  "nav",
6061
6401
  {
6062
6402
  style: {
@@ -6074,7 +6414,7 @@ function WorkflowTabs({
6074
6414
  workflows.map((w) => {
6075
6415
  const active = w.name === activeWorkflow;
6076
6416
  const isEditing = editingTab === w.name;
6077
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
6417
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6078
6418
  "div",
6079
6419
  {
6080
6420
  style: {
@@ -6085,7 +6425,7 @@ function WorkflowTabs({
6085
6425
  background: active ? "white" : "transparent"
6086
6426
  },
6087
6427
  children: [
6088
- isEditing ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6428
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6089
6429
  "input",
6090
6430
  {
6091
6431
  ref: inputRef,
@@ -6116,7 +6456,7 @@ function WorkflowTabs({
6116
6456
  width: Math.max(60, draftName.length * 8)
6117
6457
  }
6118
6458
  }
6119
- ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6459
+ ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6120
6460
  "button",
6121
6461
  {
6122
6462
  type: "button",
@@ -6135,7 +6475,7 @@ function WorkflowTabs({
6135
6475
  children: w.name || messages.tabs.untitled
6136
6476
  }
6137
6477
  ),
6138
- onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6478
+ onClose && !readOnly && workflows.length > 1 && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6139
6479
  "button",
6140
6480
  {
6141
6481
  type: "button",
@@ -6158,7 +6498,7 @@ function WorkflowTabs({
6158
6498
  w.name
6159
6499
  );
6160
6500
  }),
6161
- onAdd && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
6501
+ onAdd && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6162
6502
  "button",
6163
6503
  {
6164
6504
  type: "button",
@@ -6183,9 +6523,9 @@ function WorkflowTabs({
6183
6523
  ]
6184
6524
  }
6185
6525
  ),
6186
- dialectVersion && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
6187
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { flex: 1 } }),
6188
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6526
+ dialectVersion && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6527
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1 } }),
6528
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6189
6529
  VersionBadge,
6190
6530
  {
6191
6531
  version: dialectVersion,
@@ -6201,9 +6541,9 @@ function WorkflowTabs({
6201
6541
  }
6202
6542
 
6203
6543
  // src/modals/DragConnectModal.tsx
6204
- var import_react19 = require("react");
6205
- var import_workflow_core8 = require("@cyoda/workflow-core");
6206
- var import_jsx_runtime19 = require("react/jsx-runtime");
6544
+ var import_react20 = require("react");
6545
+ var import_workflow_core9 = require("@cyoda/workflow-core");
6546
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6207
6547
  function generateDefault(toState, existing) {
6208
6548
  const base = `to_${toState}`;
6209
6549
  if (!existing.has(base)) return base;
@@ -6220,20 +6560,20 @@ function DragConnectModal({
6220
6560
  }) {
6221
6561
  const messages = useMessages();
6222
6562
  const existing = new Set(source.transitions.map((t) => t.name));
6223
- const [name, setName] = (0, import_react19.useState)(() => generateDefault(toState, existing));
6224
- const invalidFormat = !!name && !import_workflow_core8.NAME_REGEX.test(name);
6563
+ const [name, setName] = (0, import_react20.useState)(() => generateDefault(toState, existing));
6564
+ const invalidFormat = !!name && !import_workflow_core9.NAME_REGEX.test(name);
6225
6565
  const duplicate = existing.has(name);
6226
6566
  const blocked = name.length === 0 || invalidFormat || duplicate;
6227
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ModalFrame, { onCancel, children: [
6228
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6229
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6567
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ModalFrame, { onCancel, children: [
6568
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.dragConnect.title }),
6569
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { style: { margin: "6px 0 14px", fontSize: 12, color: colors.textSecondary }, children: [
6230
6570
  fromState,
6231
6571
  " \u2192 ",
6232
6572
  toState
6233
6573
  ] }),
6234
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6235
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6236
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6574
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
6575
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: messages.dragConnect.transitionName }),
6576
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6237
6577
  "input",
6238
6578
  {
6239
6579
  type: "text",
@@ -6253,11 +6593,11 @@ function DragConnectModal({
6253
6593
  }
6254
6594
  )
6255
6595
  ] }),
6256
- invalidFormat && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6257
- duplicate && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6258
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6259
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6260
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6596
+ invalidFormat && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-format", children: messages.dragConnect.invalidName }),
6597
+ duplicate && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: errorMsg, "data-testid": "dragconnect-error-duplicate", children: messages.dragConnect.duplicateName }),
6598
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
6599
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn6, "data-testid": "dragconnect-cancel", children: messages.dragConnect.cancel }),
6600
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6261
6601
  "button",
6262
6602
  {
6263
6603
  type: "button",
@@ -6292,25 +6632,25 @@ var primaryBtn3 = {
6292
6632
  };
6293
6633
 
6294
6634
  // src/modals/AddStateModal.tsx
6295
- var import_react20 = require("react");
6296
- var import_workflow_core9 = require("@cyoda/workflow-core");
6297
- var import_jsx_runtime20 = require("react/jsx-runtime");
6635
+ var import_react21 = require("react");
6636
+ var import_workflow_core10 = require("@cyoda/workflow-core");
6637
+ var import_jsx_runtime23 = require("react/jsx-runtime");
6298
6638
  function generateName(existing) {
6299
6639
  let n = 1;
6300
6640
  while (existing.includes(`state${n}`)) n++;
6301
6641
  return `state${n}`;
6302
6642
  }
6303
6643
  function AddStateModal({ existingNames, onCreate, onCancel }) {
6304
- const [name, setName] = (0, import_react20.useState)(() => generateName(existingNames));
6305
- const [error, setError] = (0, import_react20.useState)(null);
6306
- const inputRef = (0, import_react20.useRef)(null);
6307
- (0, import_react20.useEffect)(() => {
6644
+ const [name, setName] = (0, import_react21.useState)(() => generateName(existingNames));
6645
+ const [error, setError] = (0, import_react21.useState)(null);
6646
+ const inputRef = (0, import_react21.useRef)(null);
6647
+ (0, import_react21.useEffect)(() => {
6308
6648
  inputRef.current?.select();
6309
6649
  }, []);
6310
6650
  const validate = (v) => {
6311
6651
  const trimmed = v.trim();
6312
6652
  if (!trimmed) return "Name is required";
6313
- if (!import_workflow_core9.NAME_REGEX.test(trimmed)) return "Must start with a letter and contain only letters, numbers, and underscores";
6653
+ if (!import_workflow_core10.NAME_REGEX.test(trimmed)) return "Must start with a letter and contain only letters, numbers, and underscores";
6314
6654
  if (existingNames.includes(trimmed)) return `State "${trimmed}" already exists`;
6315
6655
  return null;
6316
6656
  };
@@ -6322,11 +6662,11 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6322
6662
  }
6323
6663
  onCreate(name.trim());
6324
6664
  };
6325
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6326
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6327
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6328
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6329
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6665
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ModalFrame, { onCancel, labelledBy: "add-state-title", children: [
6666
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { id: "add-state-title", style: { margin: 0, fontSize: 16 }, children: "Add State" }),
6667
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { marginTop: 16, display: "flex", flexDirection: "column", gap: 6 }, children: [
6668
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { htmlFor: "add-state-name-input", style: { fontSize: 12, color: colors.textSecondary }, children: "State name" }),
6669
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6330
6670
  "input",
6331
6671
  {
6332
6672
  ref: inputRef,
@@ -6352,7 +6692,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6352
6692
  }
6353
6693
  }
6354
6694
  ),
6355
- error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6695
+ error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6356
6696
  "div",
6357
6697
  {
6358
6698
  id: "add-state-error",
@@ -6362,8 +6702,8 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6362
6702
  }
6363
6703
  )
6364
6704
  ] }),
6365
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6366
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6705
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 20 }, children: [
6706
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6367
6707
  "button",
6368
6708
  {
6369
6709
  type: "button",
@@ -6373,7 +6713,7 @@ function AddStateModal({ existingNames, onCreate, onCancel }) {
6373
6713
  children: "Cancel"
6374
6714
  }
6375
6715
  ),
6376
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6716
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6377
6717
  "button",
6378
6718
  {
6379
6719
  type: "button",
@@ -6403,15 +6743,15 @@ var primaryBtn4 = {
6403
6743
 
6404
6744
  // src/modals/HelpModal.tsx
6405
6745
  var import_theme6 = require("@cyoda/workflow-viewer/theme");
6406
- var import_jsx_runtime21 = require("react/jsx-runtime");
6746
+ var import_jsx_runtime24 = require("react/jsx-runtime");
6407
6747
  function HelpModal({ onCancel }) {
6408
6748
  const messages = useMessages();
6409
6749
  const h = messages.help;
6410
6750
  const node = import_theme6.workflowPalette.node;
6411
6751
  const edge = import_theme6.workflowPalette.edge;
6412
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { width: 480, maxWidth: "85vw" }, children: [
6413
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
6414
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6752
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ModalFrame, { onCancel, labelledBy: "workflow-help-title", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: 480, maxWidth: "85vw" }, children: [
6753
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h2", { id: "workflow-help-title", style: { margin: 0, fontSize: 16 }, children: h.title }),
6754
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
6415
6755
  "div",
6416
6756
  {
6417
6757
  style: {
@@ -6424,48 +6764,48 @@ function HelpModal({ onCancel }) {
6424
6764
  gap: 16
6425
6765
  },
6426
6766
  children: [
6427
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Section, { title: h.statesTitle, children: [
6428
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
6429
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
6430
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: node.processing.fill, border: node.processing.border, label: h.stateProcessing }),
6431
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: node.manualReview.fill, border: node.manualReview.border, label: h.stateManualReview }),
6432
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
6433
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
6434
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
6767
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.statesTitle, children: [
6768
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.initial.fill, border: node.initial.border, label: h.stateInitial }),
6769
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.default.fill, border: node.default.border, label: h.stateDefault }),
6770
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.processing.fill, border: node.processing.border, label: h.stateProcessing }),
6771
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.manualReview.fill, border: node.manualReview.border, label: h.stateManualReview }),
6772
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: node.terminal.fill, border: node.terminal.border, label: h.stateTerminal }),
6773
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.danger, label: h.stateError }),
6774
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorRow, { fill: "#FFFFFF", border: colors.warning, label: h.stateWarning })
6435
6775
  ] }),
6436
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Section, { title: h.transitionsTitle, children: [
6437
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.automated, label: h.transitionAutomated }),
6438
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
6439
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.conditional, label: h.transitionConditional }),
6440
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.processing, label: h.transitionProcessing }),
6441
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
6442
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.loop, label: h.transitionLoop }),
6443
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LineRow, { color: edge.disabled, label: h.transitionDisabled })
6776
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.transitionsTitle, children: [
6777
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.automated, label: h.transitionAutomated }),
6778
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.manual, dashed: true, label: h.transitionManual }),
6779
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.conditional, label: h.transitionConditional }),
6780
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.processing, label: h.transitionProcessing }),
6781
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.terminal, label: h.transitionTerminal }),
6782
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.loop, label: h.transitionLoop }),
6783
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LineRow, { color: edge.disabled, label: h.transitionDisabled })
6444
6784
  ] }),
6445
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Section, { title: h.controlsTitle, children: [
6446
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
6447
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
6448
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
6449
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
6450
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
6451
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
6452
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
6785
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { title: h.controlsTitle, children: [
6786
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "A", label: h.shortcutAddState }),
6787
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "L", label: h.shortcutAutoLayout }),
6788
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 Z", label: h.shortcutUndo }),
6789
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 \u21E7 Z", label: h.shortcutRedo }),
6790
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Ctrl/\u2318 S", label: h.shortcutSave }),
6791
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Delete", label: h.shortcutDelete }),
6792
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ShortcutRow, { keys: "Esc", label: h.shortcutEscape })
6453
6793
  ] }),
6454
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Section, { title: h.tipsTitle, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
6455
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: h.tipDoubleClick }),
6456
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: h.tipConnect }),
6457
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: h.tipSelect }),
6458
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: h.tipMove })
6794
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Section, { title: h.tipsTitle, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: colors.textSecondary, display: "flex", flexDirection: "column", gap: 6 }, children: [
6795
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipDoubleClick }),
6796
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipConnect }),
6797
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipSelect }),
6798
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("li", { children: h.tipMove })
6459
6799
  ] }) })
6460
6800
  ]
6461
6801
  }
6462
6802
  ),
6463
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
6803
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtnStyle, "data-testid": "help-modal-close", children: h.close }) })
6464
6804
  ] }) });
6465
6805
  }
6466
6806
  function Section({ title, children }) {
6467
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
6468
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6807
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
6808
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6469
6809
  "h3",
6470
6810
  {
6471
6811
  style: {
@@ -6479,12 +6819,12 @@ function Section({ title, children }) {
6479
6819
  children: title
6480
6820
  }
6481
6821
  ),
6482
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6822
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children })
6483
6823
  ] });
6484
6824
  }
6485
6825
  function ColorRow({ fill, border, label }) {
6486
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6487
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6826
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6827
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6488
6828
  "span",
6489
6829
  {
6490
6830
  style: {
@@ -6497,12 +6837,12 @@ function ColorRow({ fill, border, label }) {
6497
6837
  }
6498
6838
  }
6499
6839
  ),
6500
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: label })
6840
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
6501
6841
  ] });
6502
6842
  }
6503
6843
  function LineRow({ color, label, dashed }) {
6504
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6505
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6844
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6845
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("svg", { width: "28", height: "14", style: { flexShrink: 0 }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6506
6846
  "line",
6507
6847
  {
6508
6848
  x1: "2",
@@ -6515,12 +6855,12 @@ function LineRow({ color, label, dashed }) {
6515
6855
  ...dashed ? { strokeDasharray: "3 3" } : {}
6516
6856
  }
6517
6857
  ) }),
6518
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: label })
6858
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
6519
6859
  ] });
6520
6860
  }
6521
6861
  function ShortcutRow({ keys, label }) {
6522
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6523
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6862
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 13, color: colors.textPrimary }, children: [
6863
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6524
6864
  "kbd",
6525
6865
  {
6526
6866
  style: {
@@ -6540,12 +6880,12 @@ function ShortcutRow({ keys, label }) {
6540
6880
  children: keys
6541
6881
  }
6542
6882
  ),
6543
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: label })
6883
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label })
6544
6884
  ] });
6545
6885
  }
6546
6886
 
6547
6887
  // src/modals/VersionSwitchModal.tsx
6548
- var import_jsx_runtime22 = require("react/jsx-runtime");
6888
+ var import_jsx_runtime25 = require("react/jsx-runtime");
6549
6889
  function VersionSwitchModal({
6550
6890
  fromVersion,
6551
6891
  toVersion,
@@ -6553,7 +6893,7 @@ function VersionSwitchModal({
6553
6893
  onConfirm,
6554
6894
  onCancel
6555
6895
  }) {
6556
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6896
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6557
6897
  "div",
6558
6898
  {
6559
6899
  style: {
@@ -6565,7 +6905,7 @@ function VersionSwitchModal({
6565
6905
  justifyContent: "center",
6566
6906
  zIndex: 1e3
6567
6907
  },
6568
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6908
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6569
6909
  "div",
6570
6910
  {
6571
6911
  "data-testid": "version-switch-modal",
@@ -6579,8 +6919,8 @@ function VersionSwitchModal({
6579
6919
  fontFamily: "inherit"
6580
6920
  },
6581
6921
  children: [
6582
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6583
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6922
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { padding: "16px 20px 0", display: "flex", alignItems: "flex-start", gap: 12 }, children: [
6923
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6584
6924
  "div",
6585
6925
  {
6586
6926
  style: {
@@ -6597,20 +6937,20 @@ function VersionSwitchModal({
6597
6937
  children: "\u26A0\uFE0F"
6598
6938
  }
6599
6939
  ),
6600
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
6601
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6940
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6941
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { fontWeight: 600, fontSize: 14, color: "#0F172A", marginBottom: 4 }, children: [
6602
6942
  "Switch to ",
6603
6943
  toVersion,
6604
6944
  "?"
6605
6945
  ] }),
6606
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6946
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { color: "#475569", lineHeight: 1.5, fontSize: 13 }, children: [
6607
6947
  "Switching to ",
6608
6948
  toVersion,
6609
6949
  " will remove data not supported in that dialect:"
6610
6950
  ] })
6611
6951
  ] })
6612
6952
  ] }),
6613
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6953
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6614
6954
  "div",
6615
6955
  {
6616
6956
  style: {
@@ -6623,17 +6963,17 @@ function VersionSwitchModal({
6623
6963
  fontSize: 12
6624
6964
  },
6625
6965
  children: [
6626
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
6627
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: w }, i)) })
6966
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { fontWeight: 600, marginBottom: 6 }, children: "Will be removed:" }),
6967
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ul", { style: { margin: 0, paddingLeft: 16, lineHeight: 1.8 }, children: warnings.map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: w }, i)) })
6628
6968
  ]
6629
6969
  }
6630
6970
  ),
6631
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6971
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { padding: "10px 20px 0 64px", color: "#64748B", fontSize: 12, lineHeight: 1.5 }, children: [
6632
6972
  "This cannot be undone. You can switch back to ",
6633
6973
  fromVersion,
6634
6974
  " any time, but the removed data will not be restored."
6635
6975
  ] }),
6636
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6976
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6637
6977
  "div",
6638
6978
  {
6639
6979
  style: {
@@ -6645,7 +6985,7 @@ function VersionSwitchModal({
6645
6985
  marginTop: 16
6646
6986
  },
6647
6987
  children: [
6648
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6988
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6649
6989
  "button",
6650
6990
  {
6651
6991
  type: "button",
@@ -6663,7 +7003,7 @@ function VersionSwitchModal({
6663
7003
  children: "Cancel"
6664
7004
  }
6665
7005
  ),
6666
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
7006
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6667
7007
  "button",
6668
7008
  {
6669
7009
  type: "button",
@@ -6697,17 +7037,17 @@ function VersionSwitchModal({
6697
7037
  }
6698
7038
 
6699
7039
  // src/components/CommentNode.tsx
6700
- var import_react21 = require("react");
6701
- var import_jsx_runtime23 = require("react/jsx-runtime");
7040
+ var import_react22 = require("react");
7041
+ var import_jsx_runtime26 = require("react/jsx-runtime");
6702
7042
  function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6703
- const [editing, setEditing] = (0, import_react21.useState)(false);
6704
- const [draft, setDraft] = (0, import_react21.useState)(comment.text);
6705
- const textareaRef = (0, import_react21.useRef)(null);
7043
+ const [editing, setEditing] = (0, import_react22.useState)(false);
7044
+ const [draft, setDraft] = (0, import_react22.useState)(comment.text);
7045
+ const textareaRef = (0, import_react22.useRef)(null);
6706
7046
  const commitEdit = () => {
6707
7047
  setEditing(false);
6708
7048
  if (draft !== comment.text) onUpdate({ text: draft });
6709
7049
  };
6710
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
7050
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6711
7051
  "div",
6712
7052
  {
6713
7053
  "data-testid": `comment-${comment.id}`,
@@ -6728,8 +7068,8 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6728
7068
  userSelect: "none"
6729
7069
  },
6730
7070
  children: [
6731
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
6732
- !disabled && !editing && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7071
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginBottom: 4 }, children: [
7072
+ !disabled && !editing && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6733
7073
  "button",
6734
7074
  {
6735
7075
  type: "button",
@@ -6744,7 +7084,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6744
7084
  children: "\u270F\uFE0F"
6745
7085
  }
6746
7086
  ),
6747
- !disabled && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7087
+ !disabled && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6748
7088
  "button",
6749
7089
  {
6750
7090
  type: "button",
@@ -6756,7 +7096,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6756
7096
  }
6757
7097
  )
6758
7098
  ] }),
6759
- editing ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7099
+ editing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6760
7100
  "textarea",
6761
7101
  {
6762
7102
  ref: textareaRef,
@@ -6782,7 +7122,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6782
7122
  },
6783
7123
  "data-testid": `comment-textarea-${comment.id}`
6784
7124
  }
6785
- ) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7125
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6786
7126
  "div",
6787
7127
  {
6788
7128
  onDoubleClick: () => {
@@ -6792,7 +7132,7 @@ function CommentNode({ comment, disabled, onUpdate, onRemove }) {
6792
7132
  }
6793
7133
  },
6794
7134
  style: { whiteSpace: "pre-wrap", wordBreak: "break-word", minHeight: 20 },
6795
- children: comment.text || /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("em", { style: { color: "#94a3b8" }, children: "empty note" })
7135
+ children: comment.text || /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("em", { style: { color: "#94a3b8" }, children: "empty note" })
6796
7136
  }
6797
7137
  )
6798
7138
  ]
@@ -6810,9 +7150,9 @@ var iconBtn = {
6810
7150
  };
6811
7151
 
6812
7152
  // src/components/WorkflowJsonEditor.tsx
6813
- var import_react22 = require("react");
7153
+ var import_react23 = require("react");
6814
7154
  var import_workflow_monaco2 = require("@cyoda/workflow-monaco");
6815
- var import_jsx_runtime24 = require("react/jsx-runtime");
7155
+ var import_jsx_runtime27 = require("react/jsx-runtime");
6816
7156
  function WorkflowJsonEditor({
6817
7157
  document: document2,
6818
7158
  issues,
@@ -6824,20 +7164,20 @@ function WorkflowJsonEditor({
6824
7164
  onSelectionChange,
6825
7165
  onStatusChange
6826
7166
  }) {
6827
- const containerRef = (0, import_react22.useRef)(null);
6828
- const documentRef = (0, import_react22.useRef)(document2);
6829
- const issuesRef = (0, import_react22.useRef)(issues);
6830
- const readOnlyRef = (0, import_react22.useRef)(readOnly);
6831
- const onPatchRef = (0, import_react22.useRef)(onPatch);
6832
- const onSelectionChangeRef = (0, import_react22.useRef)(onSelectionChange);
6833
- const onStatusChangeRef = (0, import_react22.useRef)(onStatusChange);
6834
- const editorRef = (0, import_react22.useRef)(null);
6835
- const controllerRef = (0, import_react22.useRef)(null);
6836
- const schemaHandleRef = (0, import_react22.useRef)(null);
6837
- const cursorBridgeRef = (0, import_react22.useRef)(null);
6838
- const applyingGraphSelectionRef = (0, import_react22.useRef)(false);
6839
- const visibleRef = (0, import_react22.useRef)(visible);
6840
- const [status, setStatus] = (0, import_react22.useState)({ status: "idle" });
7167
+ const containerRef = (0, import_react23.useRef)(null);
7168
+ const documentRef = (0, import_react23.useRef)(document2);
7169
+ const issuesRef = (0, import_react23.useRef)(issues);
7170
+ const readOnlyRef = (0, import_react23.useRef)(readOnly);
7171
+ const onPatchRef = (0, import_react23.useRef)(onPatch);
7172
+ const onSelectionChangeRef = (0, import_react23.useRef)(onSelectionChange);
7173
+ const onStatusChangeRef = (0, import_react23.useRef)(onStatusChange);
7174
+ const editorRef = (0, import_react23.useRef)(null);
7175
+ const controllerRef = (0, import_react23.useRef)(null);
7176
+ const schemaHandleRef = (0, import_react23.useRef)(null);
7177
+ const cursorBridgeRef = (0, import_react23.useRef)(null);
7178
+ const applyingGraphSelectionRef = (0, import_react23.useRef)(false);
7179
+ const visibleRef = (0, import_react23.useRef)(visible);
7180
+ const [status, setStatus] = (0, import_react23.useState)({ status: "idle" });
6841
7181
  documentRef.current = document2;
6842
7182
  issuesRef.current = issues;
6843
7183
  readOnlyRef.current = readOnly;
@@ -6845,7 +7185,7 @@ function WorkflowJsonEditor({
6845
7185
  onPatchRef.current = onPatch;
6846
7186
  onSelectionChangeRef.current = onSelectionChange;
6847
7187
  onStatusChangeRef.current = onStatusChange;
6848
- const selectedId = (0, import_react22.useMemo)(
7188
+ const selectedId = (0, import_react23.useMemo)(
6849
7189
  () => selectionToJsonId(document2, selection),
6850
7190
  [document2, selection]
6851
7191
  );
@@ -6853,7 +7193,7 @@ function WorkflowJsonEditor({
6853
7193
  const modelUri = config?.modelUri;
6854
7194
  const editorOptions = config?.editorOptions;
6855
7195
  const debounceMs = config?.debounceMs;
6856
- (0, import_react22.useEffect)(() => {
7196
+ (0, import_react23.useEffect)(() => {
6857
7197
  if (!monaco || !containerRef.current || editorRef.current) return;
6858
7198
  const model = monaco.editor.createModel(
6859
7199
  "",
@@ -6908,7 +7248,7 @@ function WorkflowJsonEditor({
6908
7248
  model.dispose();
6909
7249
  };
6910
7250
  }, [monaco, modelUri]);
6911
- (0, import_react22.useEffect)(() => {
7251
+ (0, import_react23.useEffect)(() => {
6912
7252
  const editor = editorRef.current;
6913
7253
  const controller = controllerRef.current;
6914
7254
  if (!editor || !controller || !config) return;
@@ -6916,17 +7256,17 @@ function WorkflowJsonEditor({
6916
7256
  controller.syncFromDocument(document2);
6917
7257
  controller.renderIssues(issues, document2);
6918
7258
  }, [config, document2, issues, readOnly]);
6919
- (0, import_react22.useEffect)(() => {
7259
+ (0, import_react23.useEffect)(() => {
6920
7260
  if (!visible) return;
6921
7261
  editorRef.current?.layout?.();
6922
7262
  }, [visible]);
6923
- (0, import_react22.useEffect)(() => {
7263
+ (0, import_react23.useEffect)(() => {
6924
7264
  if (!config) {
6925
7265
  setStatus({ status: "idle" });
6926
7266
  onStatusChangeRef.current?.({ status: "idle" });
6927
7267
  }
6928
7268
  }, [config]);
6929
- (0, import_react22.useEffect)(() => {
7269
+ (0, import_react23.useEffect)(() => {
6930
7270
  const editor = editorRef.current;
6931
7271
  if (!editor || !visible || !selectedId) return;
6932
7272
  applyingGraphSelectionRef.current = true;
@@ -6937,7 +7277,7 @@ function WorkflowJsonEditor({
6937
7277
  return () => window.clearTimeout(timeout);
6938
7278
  }, [document2, selectedId, visible]);
6939
7279
  if (!config) {
6940
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7280
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6941
7281
  "div",
6942
7282
  {
6943
7283
  "data-testid": "workflow-json-unavailable",
@@ -6952,11 +7292,11 @@ function WorkflowJsonEditor({
6952
7292
  textAlign: "center",
6953
7293
  background: "#F8FAFC"
6954
7294
  },
6955
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(UnavailableMessage, {})
7295
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UnavailableMessage, {})
6956
7296
  }
6957
7297
  );
6958
7298
  }
6959
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
7299
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6960
7300
  "div",
6961
7301
  {
6962
7302
  "data-testid": "workflow-json-editor",
@@ -6968,8 +7308,8 @@ function WorkflowJsonEditor({
6968
7308
  minHeight: 0
6969
7309
  },
6970
7310
  children: [
6971
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(JsonStatusBanner, { status }),
6972
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7311
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(JsonStatusBanner, { status }),
7312
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6973
7313
  "div",
6974
7314
  {
6975
7315
  ref: containerRef,
@@ -6982,7 +7322,7 @@ function WorkflowJsonEditor({
6982
7322
  }
6983
7323
  function UnavailableMessage() {
6984
7324
  const messages = useMessages();
6985
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, { children: messages.editorView.unavailable });
7325
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: messages.editorView.unavailable });
6986
7326
  }
6987
7327
  function JsonStatusBanner({ status }) {
6988
7328
  const messages = useMessages();
@@ -6991,7 +7331,7 @@ function JsonStatusBanner({ status }) {
6991
7331
  }
6992
7332
  const tone = status.status === "semantic-errors" ? { border: "#FCD34D", bg: "#FFFBEB", text: "#92400E" } : { border: "#FCA5A5", bg: "#FEF2F2", text: "#991B1B" };
6993
7333
  const body = status.status === "semantic-errors" ? messages.editorView.semanticErrors : status.status === "invalid-schema" ? messages.editorView.invalidSchema : `${messages.editorView.invalidJson}${status.message ? ` ${status.message}` : ""}`;
6994
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7334
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6995
7335
  "div",
6996
7336
  {
6997
7337
  role: "status",
@@ -7035,7 +7375,7 @@ function selectionFromJsonId(doc, id) {
7035
7375
  }
7036
7376
 
7037
7377
  // src/components/WorkflowEditor.tsx
7038
- var import_jsx_runtime25 = require("react/jsx-runtime");
7378
+ var import_jsx_runtime28 = require("react/jsx-runtime");
7039
7379
  function hasPersistedWorkflowUi(meta) {
7040
7380
  return !!meta && Object.values(meta).some((value) => value !== void 0);
7041
7381
  }
@@ -7081,9 +7421,9 @@ function WorkflowEditor({
7081
7421
  onJsonStatusChange,
7082
7422
  developerMode = false
7083
7423
  }) {
7084
- const mergedMessages = (0, import_react23.useMemo)(() => mergeMessages(messages), [messages]);
7085
- const editorConfig = (0, import_react23.useMemo)(() => ({ developerMode }), [developerMode]);
7086
- const initialDocumentWithLayout = (0, import_react23.useMemo)(() => {
7424
+ const mergedMessages = (0, import_react24.useMemo)(() => mergeMessages(messages), [messages]);
7425
+ const editorConfig = (0, import_react24.useMemo)(() => ({ developerMode }), [developerMode]);
7426
+ const initialDocumentWithLayout = (0, import_react24.useMemo)(() => {
7087
7427
  if (localStorageKey === null) return initialDocument;
7088
7428
  try {
7089
7429
  const stored = localStorage.getItem(localStorageKey);
@@ -7102,36 +7442,46 @@ function WorkflowEditor({
7102
7442
  }
7103
7443
  }, []);
7104
7444
  const [state, actions] = useEditorStore(initialDocumentWithLayout, mode);
7105
- const [isFullscreen, setIsFullscreen] = (0, import_react23.useState)(false);
7106
- const [inspectorWidth, setInspectorWidth] = (0, import_react23.useState)(384);
7107
- const editorContainerRef = (0, import_react23.useRef)(null);
7108
- const [pendingDelete, setPendingDelete] = (0, import_react23.useState)(null);
7109
- const [pendingConnect, setPendingConnect] = (0, import_react23.useState)(null);
7110
- const [pendingAddState, setPendingAddState] = (0, import_react23.useState)(null);
7111
- const [helpOpen, setHelpOpen] = (0, import_react23.useState)(false);
7112
- const [reconnectError, setReconnectError] = (0, import_react23.useState)(null);
7113
- const [layoutKey, setLayoutKey] = (0, import_react23.useState)(0);
7114
- const [activeSurface, setActiveSurface] = (0, import_react23.useState)("graph");
7115
- const [jsonStatus, setJsonStatus] = (0, import_react23.useState)({ status: "idle" });
7116
- const [openIssueSeverity, setOpenIssueSeverity] = (0, import_react23.useState)(null);
7117
- const [inspectorOpen, setInspectorOpen] = (0, import_react23.useState)(false);
7118
- const [pendingVersionSwitch, setPendingVersionSwitch] = (0, import_react23.useState)(null);
7119
- const selectionRef = (0, import_react23.useRef)(state.selection);
7120
- const documentStateRef = (0, import_react23.useRef)(state.document);
7121
- const activeWorkflowRef = (0, import_react23.useRef)(state.activeWorkflow);
7122
- const pendingSelectionRestoreRef = (0, import_react23.useRef)(null);
7123
- const newStatePositionRef = (0, import_react23.useRef)(null);
7124
- (0, import_react23.useEffect)(() => {
7445
+ const [isFullscreen, setIsFullscreen] = (0, import_react24.useState)(false);
7446
+ const [inspectorWidth, setInspectorWidth] = (0, import_react24.useState)(384);
7447
+ const editorContainerRef = (0, import_react24.useRef)(null);
7448
+ const [pendingDelete, setPendingDelete] = (0, import_react24.useState)(null);
7449
+ const [pendingConnect, setPendingConnect] = (0, import_react24.useState)(null);
7450
+ const [pendingAddState, setPendingAddState] = (0, import_react24.useState)(null);
7451
+ const [helpOpen, setHelpOpen] = (0, import_react24.useState)(false);
7452
+ const [reconnectError, setReconnectError] = (0, import_react24.useState)(null);
7453
+ const [layoutKey, setLayoutKey] = (0, import_react24.useState)(0);
7454
+ const [activeSurface, setActiveSurface] = (0, import_react24.useState)("graph");
7455
+ const [jsonStatus, setJsonStatus] = (0, import_react24.useState)({ status: "idle" });
7456
+ const [openIssueSeverity, setOpenIssueSeverity] = (0, import_react24.useState)(null);
7457
+ const [inspectorOpen, setInspectorOpen] = (0, import_react24.useState)(false);
7458
+ const [placement, setPlacement] = (0, import_react24.useState)(() => {
7459
+ const loaded = loadPlacement(localStorageKey);
7460
+ if (loaded) {
7461
+ return {
7462
+ ...loaded,
7463
+ rect: clampRect(loaded.rect, { w: window.innerWidth, h: window.innerHeight })
7464
+ };
7465
+ }
7466
+ return { mode: "docked", rect: { left: 120, top: 96, width: 460, height: 560 } };
7467
+ });
7468
+ const [pendingVersionSwitch, setPendingVersionSwitch] = (0, import_react24.useState)(null);
7469
+ const selectionRef = (0, import_react24.useRef)(state.selection);
7470
+ const documentStateRef = (0, import_react24.useRef)(state.document);
7471
+ const activeWorkflowRef = (0, import_react24.useRef)(state.activeWorkflow);
7472
+ const pendingSelectionRestoreRef = (0, import_react24.useRef)(null);
7473
+ const newStatePositionRef = (0, import_react24.useRef)(null);
7474
+ (0, import_react24.useEffect)(() => {
7125
7475
  selectionRef.current = state.selection;
7126
7476
  }, [state.selection]);
7127
- (0, import_react23.useEffect)(() => {
7477
+ (0, import_react24.useEffect)(() => {
7128
7478
  documentStateRef.current = state.document;
7129
7479
  activeWorkflowRef.current = state.activeWorkflow;
7130
7480
  }, [state.document, state.activeWorkflow]);
7131
- (0, import_react23.useEffect)(() => {
7481
+ (0, import_react24.useEffect)(() => {
7132
7482
  onChange?.(state.document);
7133
7483
  }, [state.document, onChange]);
7134
- (0, import_react23.useEffect)(() => {
7484
+ (0, import_react24.useEffect)(() => {
7135
7485
  try {
7136
7486
  const toStore = {};
7137
7487
  for (const [wfName, ui] of Object.entries(state.document.meta.workflowUi)) {
@@ -7150,58 +7500,63 @@ function WorkflowEditor({
7150
7500
  } catch {
7151
7501
  }
7152
7502
  }, [state.document.meta.workflowUi, localStorageKey, onWorkflowUiChange]);
7153
- (0, import_react23.useEffect)(() => {
7503
+ (0, import_react24.useEffect)(() => {
7154
7504
  if (!onLayoutMetadataChange || !state.activeWorkflow) return;
7155
7505
  const ui = state.document.meta.workflowUi[state.activeWorkflow];
7156
7506
  if (ui) onLayoutMetadataChange(ui);
7157
7507
  }, [state.document.meta.workflowUi, state.activeWorkflow, onLayoutMetadataChange]);
7158
- const handleInspectorResizeStart = (0, import_react23.useCallback)((e) => {
7159
- e.preventDefault();
7160
- const startX = e.clientX;
7161
- const startWidth = inspectorWidth;
7162
- const onMove = (ev) => {
7163
- const delta = startX - ev.clientX;
7164
- setInspectorWidth(Math.max(360, startWidth + delta));
7165
- };
7166
- const onUp = () => {
7167
- document.removeEventListener("mousemove", onMove);
7168
- document.removeEventListener("mouseup", onUp);
7169
- };
7170
- document.addEventListener("mousemove", onMove);
7171
- document.addEventListener("mouseup", onUp);
7172
- }, [inspectorWidth]);
7173
- const handleToggleFullscreen = (0, import_react23.useCallback)(() => {
7508
+ (0, import_react24.useEffect)(() => {
7509
+ savePlacement(localStorageKey, placement);
7510
+ }, [placement, localStorageKey]);
7511
+ const toggleDock = (0, import_react24.useCallback)(() => {
7512
+ setPlacement((p) => {
7513
+ const viewport = { w: window.innerWidth, h: window.innerHeight };
7514
+ if (p.mode === "docked") {
7515
+ return { mode: "floating", rect: clampRect(p.rect, viewport) };
7516
+ }
7517
+ return { ...p, mode: "docked" };
7518
+ });
7519
+ }, []);
7520
+ const minimizeInspector = (0, import_react24.useCallback)(() => {
7521
+ setPlacement(
7522
+ (p) => p.mode === "minimized" ? p : { mode: "minimized", rect: p.rect, restoreMode: p.mode }
7523
+ );
7524
+ }, []);
7525
+ const restoreInspector = (0, import_react24.useCallback)(() => {
7526
+ setPlacement((p) => {
7527
+ if (p.mode !== "minimized") return p;
7528
+ const back = p.restoreMode ?? "docked";
7529
+ if (back === "floating") {
7530
+ return { mode: "floating", rect: clampRect(p.rect, { w: window.innerWidth, h: window.innerHeight }) };
7531
+ }
7532
+ return { mode: "docked", rect: p.rect };
7533
+ });
7534
+ }, []);
7535
+ const handleToggleFullscreen = (0, import_react24.useCallback)(() => {
7174
7536
  setIsFullscreen((v) => !v);
7175
7537
  }, []);
7176
7538
  const readOnly = state.mode === "viewer";
7177
- const derived = (0, import_react23.useMemo)(
7539
+ const derived = (0, import_react24.useMemo)(
7178
7540
  () => deriveFromDocument(state.document),
7179
7541
  [state.document]
7180
7542
  );
7181
- const dispatch = (0, import_react23.useCallback)(
7543
+ const dispatch = (0, import_react24.useCallback)(
7182
7544
  (patch) => {
7183
7545
  if (patch.op === "setCriterion" && patch.host.kind === "transition") {
7184
7546
  const restoreSelection = {
7185
7547
  kind: "transition",
7186
7548
  transitionUuid: patch.host.transitionUuid
7187
7549
  };
7188
- pendingSelectionRestoreRef.current = restoreSelection;
7189
- window.setTimeout(() => {
7190
- if (sameSelection(pendingSelectionRestoreRef.current, restoreSelection)) {
7191
- actions.setSelection(restoreSelection);
7192
- pendingSelectionRestoreRef.current = null;
7193
- }
7194
- }, 50);
7195
7550
  actions.dispatchTransaction({
7196
7551
  summary: patch.criterion ? "Set criterion" : "Clear criterion",
7197
7552
  patches: [patch],
7198
- inverses: [(0, import_workflow_core10.invertPatch)(state.document, patch)],
7553
+ inverses: [(0, import_workflow_core11.invertPatch)(state.document, patch)],
7199
7554
  selectionAfter: restoreSelection
7200
7555
  });
7201
7556
  return;
7202
7557
  }
7203
7558
  if (patch.op === "renameState" && selectionRef.current?.kind === "state" && selectionRef.current.stateCode === patch.from && selectionRef.current.workflow === patch.workflow) {
7204
- const nextDoc = (0, import_workflow_core10.applyPatch)(state.document, patch);
7559
+ const nextDoc = (0, import_workflow_core11.applyPatch)(state.document, patch);
7205
7560
  const newNodeId = Object.entries(nextDoc.meta.ids.states).find(([, ptr]) => ptr.workflow === patch.workflow && ptr.state === patch.to)?.[0] ?? "";
7206
7561
  actions.dispatchTransaction({
7207
7562
  summary: `Rename state "${patch.from}" \u2192 "${patch.to}"`,
@@ -7212,7 +7567,7 @@ function WorkflowEditor({
7212
7567
  return;
7213
7568
  }
7214
7569
  if (patch.op === "moveTransitionSource") {
7215
- const nextDoc = (0, import_workflow_core10.applyPatch)(state.document, patch);
7570
+ const nextDoc = (0, import_workflow_core11.applyPatch)(state.document, patch);
7216
7571
  const newUuid = transitionUuidByName(nextDoc, patch.workflow, patch.toState, patch.transitionName);
7217
7572
  actions.dispatchTransaction({
7218
7573
  summary: `Move transition "${patch.transitionName}" to "${patch.toState}"`,
@@ -7226,7 +7581,7 @@ function WorkflowEditor({
7226
7581
  },
7227
7582
  [actions, state.document]
7228
7583
  );
7229
- const handleJsonStatusChange = (0, import_react23.useCallback)(
7584
+ const handleJsonStatusChange = (0, import_react24.useCallback)(
7230
7585
  (status) => {
7231
7586
  setJsonStatus(status);
7232
7587
  onJsonStatusChange?.(status);
@@ -7238,7 +7593,7 @@ function WorkflowEditor({
7238
7593
  const inspectorVisible = chrome?.inspector !== false && inspectorOpen && (!enableJsonEditor || jsonEditorPlacement !== "tab" || activeSurface === "graph");
7239
7594
  const saveBlockedByJson = jsonStatus.status === "invalid-json" || jsonStatus.status === "invalid-schema";
7240
7595
  const saveDisabled = readOnly || derived.errorCount > 0 || saveBlockedByJson;
7241
- const handleNodeDragStop = (0, import_react23.useCallback)(
7596
+ const handleNodeDragStop = (0, import_react24.useCallback)(
7242
7597
  (nodeId, _x, _y, allPositions) => {
7243
7598
  const ids = state.document.meta.ids.states;
7244
7599
  const patches = [];
@@ -7259,12 +7614,12 @@ function WorkflowEditor({
7259
7614
  }
7260
7615
  }
7261
7616
  }
7262
- const inverses = patches.map((p) => (0, import_workflow_core10.invertPatch)(state.document, p));
7617
+ const inverses = patches.map((p) => (0, import_workflow_core11.invertPatch)(state.document, p));
7263
7618
  actions.dispatchTransaction({ patches, inverses, summary: "Move state" });
7264
7619
  },
7265
7620
  [state.document, derived.graph, actions]
7266
7621
  );
7267
- const handleAutoLayout = (0, import_react23.useCallback)(() => {
7622
+ const handleAutoLayout = (0, import_react24.useCallback)(() => {
7268
7623
  const workflow = state.activeWorkflow;
7269
7624
  if (!workflow) return;
7270
7625
  const workflowUi = { ...state.document.meta.workflowUi };
@@ -7279,11 +7634,11 @@ function WorkflowEditor({
7279
7634
  );
7280
7635
  setLayoutKey((k) => k + 1);
7281
7636
  }, [state.activeWorkflow, state.document, actions]);
7282
- const openAddStateModal = (0, import_react23.useCallback)((position) => {
7637
+ const openAddStateModal = (0, import_react24.useCallback)((position) => {
7283
7638
  const resolved = position ?? newStatePositionRef.current?.() ?? void 0;
7284
7639
  setPendingAddState(resolved ? { position: resolved } : {});
7285
7640
  }, []);
7286
- const pinnedNodes = (0, import_react23.useMemo)(() => {
7641
+ const pinnedNodes = (0, import_react24.useMemo)(() => {
7287
7642
  const workflow = state.activeWorkflow;
7288
7643
  if (!workflow) return void 0;
7289
7644
  const layoutNodes = externalLayoutMeta?.layout?.nodes ?? state.document.meta.workflowUi[workflow]?.layout?.nodes;
@@ -7303,12 +7658,12 @@ function WorkflowEditor({
7303
7658
  state.document.meta.workflowUi,
7304
7659
  externalLayoutMeta
7305
7660
  ]);
7306
- const transitionPositions = (0, import_react23.useMemo)(() => {
7661
+ const transitionPositions = (0, import_react24.useMemo)(() => {
7307
7662
  const workflow = state.activeWorkflow;
7308
7663
  if (!workflow) return void 0;
7309
7664
  return state.document.meta.workflowUi[workflow]?.transitionPositions;
7310
7665
  }, [state.activeWorkflow, state.document.meta.workflowUi]);
7311
- const handleTransitionLabelDragEnd = (0, import_react23.useCallback)(
7666
+ const handleTransitionLabelDragEnd = (0, import_react24.useCallback)(
7312
7667
  (edgeId, x, y) => {
7313
7668
  actions.dispatchTransaction({
7314
7669
  summary: "Move transition label",
@@ -7318,17 +7673,17 @@ function WorkflowEditor({
7318
7673
  },
7319
7674
  [actions]
7320
7675
  );
7321
- const handleVersionChange = (0, import_react23.useCallback)(
7676
+ const handleVersionChange = (0, import_react24.useCallback)(
7322
7677
  (targetVersion) => {
7323
- const wireJson = (0, import_workflow_core10.serializeImportPayload)(state.document);
7324
- const result = (0, import_workflow_core10.parseImportPayload)(wireJson, state.document.meta, { sourceVersion: targetVersion });
7678
+ const wireJson = (0, import_workflow_core11.serializeImportPayload)(state.document);
7679
+ const result = (0, import_workflow_core11.parseImportPayload)(wireJson, state.document.meta, { sourceVersion: targetVersion });
7325
7680
  if (!result.ok || !result.document) return;
7326
7681
  const docWithVersion = {
7327
7682
  ...result.document,
7328
7683
  meta: { ...result.document.meta, cyodaVersion: targetVersion }
7329
7684
  };
7330
7685
  const beforeJson = wireJson;
7331
- const afterJson = (0, import_workflow_core10.serializeImportPayload)(docWithVersion);
7686
+ const afterJson = (0, import_workflow_core11.serializeImportPayload)(docWithVersion);
7332
7687
  const parseWarnings = result.warnings ?? [];
7333
7688
  const isLossy = beforeJson !== afterJson || parseWarnings.length > 0;
7334
7689
  const warnings = parseWarnings.length > 0 ? parseWarnings : isLossy ? ["Some fields supported in the current version are not present in the target version and will be removed."] : [];
@@ -7356,7 +7711,7 @@ function WorkflowEditor({
7356
7711
  const resolved = resolveConnection(state.document, connection);
7357
7712
  if (resolved) setPendingConnect(resolved);
7358
7713
  };
7359
- const handleReconnect = (0, import_react23.useCallback)(
7714
+ const handleReconnect = (0, import_react24.useCallback)(
7360
7715
  (edge, connection) => {
7361
7716
  setReconnectError(null);
7362
7717
  const tx = buildReconnectTransaction(state.document, edge, connection);
@@ -7367,7 +7722,7 @@ function WorkflowEditor({
7367
7722
  try {
7368
7723
  actions.dispatchTransaction(tx.transaction);
7369
7724
  } catch (error) {
7370
- if (error instanceof import_workflow_core10.PatchConflictError) {
7725
+ if (error instanceof import_workflow_core11.PatchConflictError) {
7371
7726
  setReconnectError(error.message);
7372
7727
  return;
7373
7728
  }
@@ -7376,7 +7731,7 @@ function WorkflowEditor({
7376
7731
  },
7377
7732
  [actions, state.document]
7378
7733
  );
7379
- const confirmConnect = (0, import_react23.useCallback)(
7734
+ const confirmConnect = (0, import_react24.useCallback)(
7380
7735
  (name) => {
7381
7736
  if (!pendingConnect) return;
7382
7737
  const addPatch = {
@@ -7386,7 +7741,7 @@ function WorkflowEditor({
7386
7741
  transition: { name, next: pendingConnect.toState, manual: false, disabled: false }
7387
7742
  };
7388
7743
  const priorUUIDs = new Set(Object.keys(state.document.meta.ids.transitions));
7389
- const afterApply = (0, import_workflow_core10.applyPatch)(state.document, addPatch);
7744
+ const afterApply = (0, import_workflow_core11.applyPatch)(state.document, addPatch);
7390
7745
  const newUUID = Object.keys(afterApply.meta.ids.transitions).find(
7391
7746
  (u) => !priorUUIDs.has(u)
7392
7747
  );
@@ -7402,7 +7757,7 @@ function WorkflowEditor({
7402
7757
  );
7403
7758
  const workflows = state.document.session.workflows;
7404
7759
  const showTabs = workflows.length > 1 || state.mode !== "viewer";
7405
- const handleSelectionChange = (0, import_react23.useCallback)(
7760
+ const handleSelectionChange = (0, import_react24.useCallback)(
7406
7761
  (selection) => {
7407
7762
  const pendingRestore = pendingSelectionRestoreRef.current;
7408
7763
  if (!selection && pendingRestore) {
@@ -7420,7 +7775,7 @@ function WorkflowEditor({
7420
7775
  },
7421
7776
  [actions]
7422
7777
  );
7423
- const confirmAddState = (0, import_react23.useCallback)(
7778
+ const confirmAddState = (0, import_react24.useCallback)(
7424
7779
  (name) => {
7425
7780
  const workflow = state.activeWorkflow;
7426
7781
  const requestedPosition = pendingAddState?.position;
@@ -7448,7 +7803,7 @@ function WorkflowEditor({
7448
7803
  [pendingAddState, state.activeWorkflow, actions]
7449
7804
  );
7450
7805
  const anyModalOpen = pendingDelete !== null || pendingConnect !== null || pendingAddState !== null || helpOpen;
7451
- const handleKeyDown = (0, import_react23.useCallback)(
7806
+ const handleKeyDown = (0, import_react24.useCallback)(
7452
7807
  (e) => {
7453
7808
  if (anyModalOpen) return;
7454
7809
  if (isTypingTarget(e.target)) return;
@@ -7508,7 +7863,7 @@ function WorkflowEditor({
7508
7863
  inspectorOpen
7509
7864
  ]
7510
7865
  );
7511
- const handleDeleteKeyDownCapture = (0, import_react23.useCallback)(
7866
+ const handleDeleteKeyDownCapture = (0, import_react24.useCallback)(
7512
7867
  (e) => {
7513
7868
  if (anyModalOpen || readOnly || isTypingTarget(e.target)) return;
7514
7869
  if (e.ctrlKey || e.metaKey || e.altKey) return;
@@ -7528,7 +7883,7 @@ function WorkflowEditor({
7528
7883
  },
7529
7884
  [anyModalOpen, readOnly, state.selection]
7530
7885
  );
7531
- (0, import_react23.useEffect)(() => {
7886
+ (0, import_react24.useEffect)(() => {
7532
7887
  const handleDocumentDeleteKeyDown = (event) => {
7533
7888
  if (anyModalOpen || readOnly || isTypingTarget(event.target)) return;
7534
7889
  if (event.ctrlKey || event.metaKey || event.altKey) return;
@@ -7551,7 +7906,7 @@ function WorkflowEditor({
7551
7906
  document.removeEventListener("keydown", handleDocumentDeleteKeyDown, true);
7552
7907
  };
7553
7908
  }, [anyModalOpen, readOnly, dispatch]);
7554
- const pendingConnectState = (0, import_react23.useMemo)(() => {
7909
+ const pendingConnectState = (0, import_react24.useMemo)(() => {
7555
7910
  if (!pendingConnect) return null;
7556
7911
  const wf = state.document.session.workflows.find(
7557
7912
  (w) => w.name === pendingConnect.workflow
@@ -7560,17 +7915,17 @@ function WorkflowEditor({
7560
7915
  return wf.states[pendingConnect.fromState] ?? null;
7561
7916
  }, [pendingConnect, state.document]);
7562
7917
  const orientation = layoutOptions?.orientation ?? "vertical";
7563
- const effectiveLayoutOptions = (0, import_react23.useMemo)(
7918
+ const effectiveLayoutOptions = (0, import_react24.useMemo)(
7564
7919
  () => ({ ...layoutOptions, pinned: pinnedNodes }),
7565
7920
  [layoutOptions, pinnedNodes]
7566
7921
  );
7567
7922
  const savedViewport = state.activeWorkflow ? state.document.meta.workflowUi[state.activeWorkflow]?.viewports?.[orientation] : void 0;
7568
- (0, import_react23.useEffect)(() => {
7923
+ (0, import_react24.useEffect)(() => {
7569
7924
  if (enableJsonEditor) return;
7570
7925
  setJsonStatus({ status: "idle" });
7571
7926
  onJsonStatusChange?.({ status: "idle" });
7572
7927
  }, [enableJsonEditor, onJsonStatusChange]);
7573
- const handleViewportChange = (0, import_react23.useCallback)(
7928
+ const handleViewportChange = (0, import_react24.useCallback)(
7574
7929
  (viewport) => {
7575
7930
  const workflow = state.activeWorkflow;
7576
7931
  if (!workflow) return;
@@ -7600,17 +7955,17 @@ function WorkflowEditor({
7600
7955
  },
7601
7956
  [actions, orientation, state.activeWorkflow, state.document]
7602
7957
  );
7603
- const handlePaneDoubleClick = (0, import_react23.useCallback)((x, y) => {
7958
+ const handlePaneDoubleClick = (0, import_react24.useCallback)((x, y) => {
7604
7959
  if (readOnly || anyModalOpen) return;
7605
7960
  openAddStateModal({ x, y });
7606
7961
  }, [anyModalOpen, openAddStateModal, readOnly]);
7607
- const graphPane = /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
7962
+ const graphPane = /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7608
7963
  "div",
7609
7964
  {
7610
7965
  "data-testid": "workflow-editor-graph-pane",
7611
7966
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%", position: "relative" },
7612
7967
  children: [
7613
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7968
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7614
7969
  Canvas,
7615
7970
  {
7616
7971
  graph: derived.graph,
@@ -7655,7 +8010,7 @@ function WorkflowEditor({
7655
8010
  helpLabel: mergedMessages.toolbar.help
7656
8011
  }
7657
8012
  ),
7658
- reconnectError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8013
+ reconnectError && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7659
8014
  "div",
7660
8015
  {
7661
8016
  role: "alert",
@@ -7680,7 +8035,7 @@ function WorkflowEditor({
7680
8035
  state.activeWorkflow && (() => {
7681
8036
  const comments = state.document.meta.workflowUi[state.activeWorkflow]?.comments;
7682
8037
  if (!comments) return null;
7683
- return Object.values(comments).map((c) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8038
+ return Object.values(comments).map((c) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7684
8039
  CommentNode,
7685
8040
  {
7686
8041
  comment: c,
@@ -7703,12 +8058,12 @@ function WorkflowEditor({
7703
8058
  ]
7704
8059
  }
7705
8060
  );
7706
- const jsonPane = enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8061
+ const jsonPane = enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7707
8062
  "div",
7708
8063
  {
7709
8064
  "data-testid": "workflow-editor-json-pane",
7710
8065
  style: { flex: 1, minWidth: 0, minHeight: 0, height: "100%" },
7711
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8066
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7712
8067
  WorkflowJsonEditor,
7713
8068
  {
7714
8069
  document: state.document,
@@ -7724,7 +8079,7 @@ function WorkflowEditor({
7724
8079
  )
7725
8080
  }
7726
8081
  ) : null;
7727
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8082
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(CriterionMonacoProvider, { value: jsonEditor?.monaco ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(I18nContext.Provider, { value: mergedMessages, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorConfigContext.Provider, { value: editorConfig, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7728
8083
  "div",
7729
8084
  {
7730
8085
  ref: editorContainerRef,
@@ -7745,7 +8100,7 @@ function WorkflowEditor({
7745
8100
  onKeyDown: handleKeyDown,
7746
8101
  tabIndex: -1,
7747
8102
  children: [
7748
- chrome?.tabs !== false && showTabs && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8103
+ chrome?.tabs !== false && showTabs && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7749
8104
  WorkflowTabs,
7750
8105
  {
7751
8106
  workflows,
@@ -7767,14 +8122,14 @@ function WorkflowEditor({
7767
8122
  });
7768
8123
  actions.setActiveWorkflow(to);
7769
8124
  },
7770
- dialectVersion: `v${state.document.meta.cyodaVersion ?? import_workflow_core10.LATEST_CYODA_VERSION}`,
7771
- supportedVersions: import_workflow_core10.SUPPORTED_CYODA_VERSIONS,
8125
+ dialectVersion: `v${state.document.meta.cyodaVersion ?? import_workflow_core11.LATEST_CYODA_VERSION}`,
8126
+ supportedVersions: import_workflow_core11.SUPPORTED_CYODA_VERSIONS,
7772
8127
  onVersionChange: handleVersionChange
7773
8128
  }
7774
8129
  ),
7775
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
7776
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
7777
- (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8130
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, display: "flex", minHeight: 0 }, children: [
8131
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
8132
+ (enableJsonEditor && jsonEditorPlacement === "tab" || !readOnly && graphVisible) && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7778
8133
  "div",
7779
8134
  {
7780
8135
  style: {
@@ -7788,8 +8143,8 @@ function WorkflowEditor({
7788
8143
  },
7789
8144
  "data-testid": "workflow-editor-surface-tabs",
7790
8145
  children: [
7791
- enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
7792
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8146
+ enableJsonEditor && jsonEditorPlacement === "tab" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
8147
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7793
8148
  SurfaceTab,
7794
8149
  {
7795
8150
  active: activeSurface === "graph",
@@ -7797,7 +8152,7 @@ function WorkflowEditor({
7797
8152
  children: mergedMessages.editorView.graph
7798
8153
  }
7799
8154
  ),
7800
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8155
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7801
8156
  SurfaceTab,
7802
8157
  {
7803
8158
  active: activeSurface === "json",
@@ -7806,8 +8161,8 @@ function WorkflowEditor({
7806
8161
  }
7807
8162
  )
7808
8163
  ] }),
7809
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { flex: 1 } }),
7810
- !readOnly && activeSurface === "graph" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8164
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { flex: 1 } }),
8165
+ !readOnly && activeSurface === "graph" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7811
8166
  "button",
7812
8167
  {
7813
8168
  type: "button",
@@ -7828,7 +8183,7 @@ function WorkflowEditor({
7828
8183
  cursor: "pointer"
7829
8184
  },
7830
8185
  children: [
7831
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M12 5v14M5 12h14" }) }),
8186
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M12 5v14M5 12h14" }) }),
7832
8187
  mergedMessages.toolbar.addStateButton
7833
8188
  ]
7834
8189
  }
@@ -7836,7 +8191,7 @@ function WorkflowEditor({
7836
8191
  ]
7837
8192
  }
7838
8193
  ),
7839
- enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8194
+ enableJsonEditor && jsonEditorPlacement === "split" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7840
8195
  "div",
7841
8196
  {
7842
8197
  style: {
@@ -7849,10 +8204,10 @@ function WorkflowEditor({
7849
8204
  "data-testid": "workflow-editor-split-view",
7850
8205
  children: [
7851
8206
  graphPane,
7852
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
8207
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { borderLeft: "1px solid #E2E8F0", minWidth: 0 }, children: jsonPane })
7853
8208
  ]
7854
8209
  }
7855
- ) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8210
+ ) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7856
8211
  "div",
7857
8212
  {
7858
8213
  style: {
@@ -7864,8 +8219,8 @@ function WorkflowEditor({
7864
8219
  flexDirection: "column"
7865
8220
  },
7866
8221
  children: [
7867
- graphVisible ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
7868
- enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8222
+ graphVisible ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { flex: 1, minHeight: 0, minWidth: 0 }, children: graphPane }) : null,
8223
+ enableJsonEditor ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7869
8224
  "div",
7870
8225
  {
7871
8226
  style: {
@@ -7882,41 +8237,36 @@ function WorkflowEditor({
7882
8237
  }
7883
8238
  )
7884
8239
  ] }),
7885
- inspectorVisible && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
7886
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7887
- "div",
7888
- {
7889
- onMouseDown: handleInspectorResizeStart,
7890
- style: {
7891
- width: 3,
7892
- flexShrink: 0,
7893
- cursor: "col-resize",
7894
- background: "transparent",
7895
- borderLeft: "1px solid #E2E8F0",
7896
- transition: "background 0.15s",
7897
- zIndex: 10
7898
- },
7899
- onMouseEnter: (e) => e.currentTarget.style.background = "#CBD5E1",
7900
- onMouseLeave: (e) => e.currentTarget.style.background = "transparent"
7901
- }
7902
- ),
7903
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7904
- Inspector,
7905
- {
7906
- document: state.document,
7907
- selection: state.selection,
7908
- issues: derived.issues,
7909
- readOnly,
7910
- onDispatch: dispatch,
7911
- onSelectionChange: handleSelectionChange,
7912
- onClose: () => handleSelectionChange(null),
7913
- onRequestDeleteState: requestDeleteState,
7914
- width: inspectorWidth
7915
- }
7916
- )
7917
- ] })
8240
+ inspectorVisible && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8241
+ InspectorFrame,
8242
+ {
8243
+ mode: placement.mode,
8244
+ rect: placement.rect,
8245
+ dockedWidth: inspectorWidth,
8246
+ onRectChange: (rect) => setPlacement((p) => ({ ...p, rect })),
8247
+ onDockedWidthChange: setInspectorWidth,
8248
+ onRestore: restoreInspector,
8249
+ onClose: () => handleSelectionChange(null),
8250
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8251
+ Inspector,
8252
+ {
8253
+ document: state.document,
8254
+ selection: state.selection,
8255
+ issues: derived.issues,
8256
+ readOnly,
8257
+ onDispatch: dispatch,
8258
+ onSelectionChange: handleSelectionChange,
8259
+ onClose: () => handleSelectionChange(null),
8260
+ onRequestDeleteState: requestDeleteState,
8261
+ docked: placement.mode === "docked",
8262
+ onToggleDock: toggleDock,
8263
+ onMinimize: minimizeInspector
8264
+ }
8265
+ )
8266
+ }
8267
+ )
7918
8268
  ] }),
7919
- pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8269
+ pendingAddState !== null && state.activeWorkflow && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7920
8270
  AddStateModal,
7921
8271
  {
7922
8272
  existingNames: Object.keys(
@@ -7928,7 +8278,7 @@ function WorkflowEditor({
7928
8278
  onCancel: () => setPendingAddState(null)
7929
8279
  }
7930
8280
  ),
7931
- pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8281
+ pendingDelete && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7932
8282
  DeleteStateModal,
7933
8283
  {
7934
8284
  document: state.document,
@@ -7938,7 +8288,7 @@ function WorkflowEditor({
7938
8288
  onCancel: () => setPendingDelete(null)
7939
8289
  }
7940
8290
  ),
7941
- pendingConnect && pendingConnectState && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8291
+ pendingConnect && pendingConnectState && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7942
8292
  DragConnectModal,
7943
8293
  {
7944
8294
  source: pendingConnectState,
@@ -7948,11 +8298,11 @@ function WorkflowEditor({
7948
8298
  onCancel: () => setPendingConnect(null)
7949
8299
  }
7950
8300
  ),
7951
- helpOpen && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(HelpModal, { onCancel: () => setHelpOpen(false) }),
7952
- pendingVersionSwitch && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8301
+ helpOpen && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(HelpModal, { onCancel: () => setHelpOpen(false) }),
8302
+ pendingVersionSwitch && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7953
8303
  VersionSwitchModal,
7954
8304
  {
7955
- fromVersion: `v${state.document.meta.cyodaVersion ?? import_workflow_core10.LATEST_CYODA_VERSION}`,
8305
+ fromVersion: `v${state.document.meta.cyodaVersion ?? import_workflow_core11.LATEST_CYODA_VERSION}`,
7956
8306
  toVersion: `v${pendingVersionSwitch.targetVersion}`,
7957
8307
  warnings: pendingVersionSwitch.warnings,
7958
8308
  onConfirm: () => {
@@ -7962,8 +8312,8 @@ function WorkflowEditor({
7962
8312
  onCancel: () => setPendingVersionSwitch(null)
7963
8313
  }
7964
8314
  ),
7965
- chrome?.toolbar !== false && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { position: "relative" }, children: [
7966
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8315
+ chrome?.toolbar !== false && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { style: { position: "relative" }, children: [
8316
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7967
8317
  Toolbar,
7968
8318
  {
7969
8319
  derived,
@@ -7978,7 +8328,7 @@ function WorkflowEditor({
7978
8328
  toolbarEnd
7979
8329
  }
7980
8330
  ),
7981
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8331
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7982
8332
  IssuesDrawer,
7983
8333
  {
7984
8334
  open: openIssueSeverity !== null,
@@ -8061,7 +8411,7 @@ function buildReconnectTransaction(doc, edge, connection) {
8061
8411
  toState,
8062
8412
  transitionName: transition.name
8063
8413
  };
8064
- const afterMove = (0, import_workflow_core10.applyPatch)(doc, movePatch);
8414
+ const afterMove = (0, import_workflow_core11.applyPatch)(doc, movePatch);
8065
8415
  const movedUuid = transitionUuidByName(afterMove, ptr.workflow, toState, transition.name);
8066
8416
  if (!movedUuid) return { ok: false };
8067
8417
  const patches = [movePatch];
@@ -8136,22 +8486,6 @@ function normalizeAnchorPair(anchors) {
8136
8486
  function sameAnchors(a, b) {
8137
8487
  return a?.source === b?.source && a?.target === b?.target;
8138
8488
  }
8139
- function sameSelection(a, b) {
8140
- if (a === b) return true;
8141
- if (!a || !b || a.kind !== b.kind) return false;
8142
- switch (a.kind) {
8143
- case "workflow":
8144
- return b.kind === "workflow" && a.workflow === b.workflow;
8145
- case "state":
8146
- return b.kind === "state" && a.workflow === b.workflow && a.stateCode === b.stateCode && a.nodeId === b.nodeId;
8147
- case "transition":
8148
- return b.kind === "transition" && a.transitionUuid === b.transitionUuid;
8149
- case "processor":
8150
- return b.kind === "processor" && a.processorUuid === b.processorUuid;
8151
- case "criterion":
8152
- 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]);
8153
- }
8154
- }
8155
8489
  function workflowForSelection(doc, selection) {
8156
8490
  if (!selection) return null;
8157
8491
  if (selection.kind === "workflow" || selection.kind === "state") return selection.workflow;
@@ -8174,7 +8508,7 @@ function SurfaceTab({
8174
8508
  onClick,
8175
8509
  children
8176
8510
  }) {
8177
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8511
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
8178
8512
  "button",
8179
8513
  {
8180
8514
  type: "button",
@@ -8229,16 +8563,16 @@ function snapToGrid(value, grid = 16) {
8229
8563
  }
8230
8564
 
8231
8565
  // src/save/useSaveFlow.ts
8232
- var import_react24 = require("react");
8233
- var import_workflow_core11 = require("@cyoda/workflow-core");
8566
+ var import_react25 = require("react");
8567
+ var import_workflow_core12 = require("@cyoda/workflow-core");
8234
8568
  function useSaveFlow(args) {
8235
8569
  const { api, document: doc, concurrencyToken, onSaved, onReload } = args;
8236
- const [status, setStatus] = (0, import_react24.useState)({ kind: "idle" });
8237
- const tokenRef = (0, import_react24.useRef)(concurrencyToken);
8570
+ const [status, setStatus] = (0, import_react25.useState)({ kind: "idle" });
8571
+ const tokenRef = (0, import_react25.useRef)(concurrencyToken);
8238
8572
  tokenRef.current = concurrencyToken;
8239
- const entityRef = (0, import_react24.useRef)(doc.session.entity);
8573
+ const entityRef = (0, import_react25.useRef)(doc.session.entity);
8240
8574
  entityRef.current = doc.session.entity;
8241
- const payloadRef = (0, import_react24.useRef)({
8575
+ const payloadRef = (0, import_react25.useRef)({
8242
8576
  importMode: doc.session.importMode,
8243
8577
  workflows: doc.session.workflows
8244
8578
  });
@@ -8246,8 +8580,8 @@ function useSaveFlow(args) {
8246
8580
  importMode: doc.session.importMode,
8247
8581
  workflows: doc.session.workflows
8248
8582
  };
8249
- const savingRef = (0, import_react24.useRef)(false);
8250
- const performImport = (0, import_react24.useCallback)(
8583
+ const savingRef = (0, import_react25.useRef)(false);
8584
+ const performImport = (0, import_react25.useCallback)(
8251
8585
  async (token) => {
8252
8586
  if (savingRef.current) return;
8253
8587
  const entity = entityRef.current;
@@ -8267,7 +8601,7 @@ function useSaveFlow(args) {
8267
8601
  onSaved(result.concurrencyToken);
8268
8602
  setStatus({ kind: "success", at: Date.now() });
8269
8603
  } catch (err) {
8270
- if (err instanceof import_workflow_core11.WorkflowApiConflictError) {
8604
+ if (err instanceof import_workflow_core12.WorkflowApiConflictError) {
8271
8605
  setStatus({
8272
8606
  kind: "conflict",
8273
8607
  serverConcurrencyToken: err.serverConcurrencyToken
@@ -8284,28 +8618,28 @@ function useSaveFlow(args) {
8284
8618
  },
8285
8619
  [api, onSaved]
8286
8620
  );
8287
- const requestSave = (0, import_react24.useCallback)(() => {
8621
+ const requestSave = (0, import_react25.useCallback)(() => {
8288
8622
  const mode = payloadRef.current.importMode;
8289
8623
  const requiresExplicitConfirm = mode === "REPLACE" || mode === "ACTIVATE";
8290
8624
  setStatus({ kind: "confirming", mode, requiresExplicitConfirm });
8291
8625
  }, []);
8292
- const confirmSave = (0, import_react24.useCallback)(
8626
+ const confirmSave = (0, import_react25.useCallback)(
8293
8627
  () => performImport(tokenRef.current),
8294
8628
  [performImport]
8295
8629
  );
8296
- const cancel = (0, import_react24.useCallback)(() => setStatus({ kind: "idle" }), []);
8297
- const forceOverwrite = (0, import_react24.useCallback)(() => performImport(null), [performImport]);
8298
- const reload = (0, import_react24.useCallback)(() => {
8630
+ const cancel = (0, import_react25.useCallback)(() => setStatus({ kind: "idle" }), []);
8631
+ const forceOverwrite = (0, import_react25.useCallback)(() => performImport(null), [performImport]);
8632
+ const reload = (0, import_react25.useCallback)(() => {
8299
8633
  onReload?.();
8300
8634
  setStatus({ kind: "idle" });
8301
8635
  }, [onReload]);
8302
- const clear = (0, import_react24.useCallback)(() => setStatus({ kind: "idle" }), []);
8636
+ const clear = (0, import_react25.useCallback)(() => setStatus({ kind: "idle" }), []);
8303
8637
  return { status, requestSave, confirmSave, cancel, forceOverwrite, reload, clear };
8304
8638
  }
8305
8639
 
8306
8640
  // src/save/SaveConfirmModal.tsx
8307
- var import_react25 = require("react");
8308
- var import_jsx_runtime26 = require("react/jsx-runtime");
8641
+ var import_react26 = require("react");
8642
+ var import_jsx_runtime29 = require("react/jsx-runtime");
8309
8643
  function SaveConfirmModal({
8310
8644
  mode,
8311
8645
  requiresExplicitConfirm,
@@ -8315,17 +8649,17 @@ function SaveConfirmModal({
8315
8649
  onCancel
8316
8650
  }) {
8317
8651
  const messages = useMessages();
8318
- const [ackMode, setAckMode] = (0, import_react25.useState)(!requiresExplicitConfirm);
8319
- const [ackWarnings, setAckWarnings] = (0, import_react25.useState)(warningCount === 0);
8652
+ const [ackMode, setAckMode] = (0, import_react26.useState)(!requiresExplicitConfirm);
8653
+ const [ackWarnings, setAckWarnings] = (0, import_react26.useState)(warningCount === 0);
8320
8654
  const blocked = !ackMode || !ackWarnings;
8321
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ModalFrame, { onCancel, children: [
8322
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
8323
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
8655
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(ModalFrame, { onCancel, children: [
8656
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { style: { margin: 0, fontSize: 16 }, children: messages.saveConfirm.title }),
8657
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { style: { margin: "12px 0", fontSize: 13, color: colors.textSecondary }, children: [
8324
8658
  messages.saveConfirm.modeLabel,
8325
8659
  ": ",
8326
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("strong", { children: mode })
8660
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("strong", { children: mode })
8327
8661
  ] }),
8328
- diffSummary2 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8662
+ diffSummary2 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8329
8663
  "pre",
8330
8664
  {
8331
8665
  style: {
@@ -8344,8 +8678,8 @@ function SaveConfirmModal({
8344
8678
  children: diffSummary2
8345
8679
  }
8346
8680
  ),
8347
- requiresExplicitConfirm && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8348
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8681
+ requiresExplicitConfirm && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { style: checkRow, "data-testid": "save-ack-mode", children: [
8682
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8349
8683
  "input",
8350
8684
  {
8351
8685
  type: "checkbox",
@@ -8353,10 +8687,10 @@ function SaveConfirmModal({
8353
8687
  onChange: (e) => setAckMode(e.target.checked)
8354
8688
  }
8355
8689
  ),
8356
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8690
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: mode === "REPLACE" ? messages.saveConfirm.ackReplace : messages.saveConfirm.ackActivate })
8357
8691
  ] }),
8358
- warningCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8359
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8692
+ warningCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { style: checkRow, "data-testid": "save-ack-warnings", children: [
8693
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8360
8694
  "input",
8361
8695
  {
8362
8696
  type: "checkbox",
@@ -8364,11 +8698,11 @@ function SaveConfirmModal({
8364
8698
  onChange: (e) => setAckWarnings(e.target.checked)
8365
8699
  }
8366
8700
  ),
8367
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8701
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: messages.saveConfirm.ackWarnings.replace("{count}", String(warningCount)) })
8368
8702
  ] }),
8369
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
8370
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
8371
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8703
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: [
8704
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", onClick: onCancel, style: ghostBtn8, "data-testid": "save-cancel", children: messages.saveConfirm.cancel }),
8705
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
8372
8706
  "button",
8373
8707
  {
8374
8708
  type: "button",
@@ -8406,10 +8740,10 @@ var primaryBtn5 = {
8406
8740
  };
8407
8741
 
8408
8742
  // src/save/ConflictBanner.tsx
8409
- var import_jsx_runtime27 = require("react/jsx-runtime");
8743
+ var import_jsx_runtime30 = require("react/jsx-runtime");
8410
8744
  function ConflictBanner({ onReload, onForceOverwrite }) {
8411
8745
  const messages = useMessages();
8412
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
8746
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
8413
8747
  "div",
8414
8748
  {
8415
8749
  style: {
@@ -8425,8 +8759,8 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8425
8759
  role: "alert",
8426
8760
  "data-testid": "conflict-banner",
8427
8761
  children: [
8428
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { flex: 1 }, children: messages.conflict.message }),
8429
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8762
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { flex: 1 }, children: messages.conflict.message }),
8763
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8430
8764
  "button",
8431
8765
  {
8432
8766
  type: "button",
@@ -8436,7 +8770,7 @@ function ConflictBanner({ onReload, onForceOverwrite }) {
8436
8770
  children: messages.conflict.reload
8437
8771
  }
8438
8772
  ),
8439
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8773
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8440
8774
  "button",
8441
8775
  {
8442
8776
  type: "button",