feat(editor): right-click context menu + reset layout

Two operator-visible features filling concrete gaps the
jai_client editor exposed:

 - Right-click on any step node opens a popup menu at the
   cursor position with three actions:
   * Duplicate — clones the step with a unique id
     (<base>_2, <base>_3, …) and offsets its position so
     the copy is visible next to the original.
   * Disconnect all inputs — keeps every with-field key
     but clears its expression value, so the step still
     declares the same inputs but no longer wires them to
     any upstream step.
   * Delete — removes the step. Any dangling $refs in
     downstream steps become run-time errors; we don't
     silently rewrite their YAML because the surprise
     would be worse than the explicit error.

 - Floating "Reset layout" button on the canvas (next to
   Fit to screen). Wipes the layout sidecar so AutoLayout
   re-runs from scratch and the topological column
   placement is restored. Auto-fits afterwards. Useful
   when manual drags have drifted into spaghetti and the
   operator wants a clean slate without losing the flow.

Implementation:
 - FlowNode gains an `onContextMenu(Offset globalPos)`
   parameter, wired to GestureDetector.onSecondaryTapDown.
 - FlowEditorController.resetLayout() — clears layout,
   re-seeds via AutoLayout, saves sidecar, notifies.
 - The menu uses Flutter's showMenu() at the global
   cursor position for native-feeling positioning.

Version bumped 0.2.2 -> 0.3.0 — first new operator-visible
feature set since the v0.2 WYSIWYG release.

Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
flemming-it 2026-06-01 16:15:57 +02:00
parent c15731fb1b
commit 296e5bfd01
4 changed files with 179 additions and 10 deletions

View file

@ -167,6 +167,18 @@ class FlowEditorController extends ChangeNotifier {
notifyListeners();
}
/// Wipe every position in the sidecar and re-run auto-
/// layout from scratch. Useful when manual drags have
/// drifted into spaghetti and the operator wants a clean
/// topological column layout again. The YAML is untouched.
void resetLayout() {
_layout = AutoLayout.layout(_graph, FlowLayout.empty());
if (_activeName != null) {
LayoutStore.saveSync(_activeName!, _layout);
}
notifyListeners();
}
/// Apply a graph-side edit (rename step, change `use`,
/// adjust `with`, add/remove step, add edge). Emits fresh
/// YAML into the text controller, then bumps the layout to