@memberjunction/ng-flow-editor 6.1.0-edge.2 → 6.1.0-edge.4
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/LICENSE +180 -4
- package/dist/lib/components/flow-editor.component.d.ts +27 -4
- package/dist/lib/components/flow-editor.component.d.ts.map +1 -1
- package/dist/lib/components/flow-editor.component.js +281 -157
- package/dist/lib/components/flow-editor.component.js.map +1 -1
- package/dist/lib/components/flow-node.component.d.ts +5 -0
- package/dist/lib/components/flow-node.component.d.ts.map +1 -1
- package/dist/lib/components/flow-node.component.js +79 -44
- package/dist/lib/components/flow-node.component.js.map +1 -1
- package/dist/lib/components/flow-toolbar.component.d.ts +3 -1
- package/dist/lib/components/flow-toolbar.component.d.ts.map +1 -1
- package/dist/lib/components/flow-toolbar.component.js +32 -4
- package/dist/lib/components/flow-toolbar.component.js.map +1 -1
- package/dist/lib/interfaces/flow-types.d.ts +52 -3
- package/dist/lib/interfaces/flow-types.d.ts.map +1 -1
- package/dist/lib/interfaces/flow-types.js +33 -1
- package/dist/lib/interfaces/flow-types.js.map +1 -1
- package/package.json +10 -10
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, Input, Output, EventEmitter, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
3
|
import { FFlowComponent, FCanvasComponent } from '@foblex/flow';
|
|
4
|
+
import { FlowBeforeContextMenuEventArgs, FlowAfterContextMenuActionEventArgs, } from '../interfaces/flow-types';
|
|
4
5
|
import { FlowStateService } from '../services/flow-state.service';
|
|
5
6
|
import { FlowLayoutService } from '../services/flow-layout.service';
|
|
6
7
|
import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
|
|
@@ -17,210 +18,232 @@ import * as i9 from "./flow-status-bar.component";
|
|
|
17
18
|
const _c0 = ["fZoomRef"];
|
|
18
19
|
const _c1 = ["canvasArea"];
|
|
19
20
|
const _c2 = (a0, a1) => ({ x: a0, y: a1 });
|
|
21
|
+
const _forTrack0 = ($index, $item) => $item.ID;
|
|
20
22
|
function FlowEditorComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
21
23
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
22
|
-
i0.ɵɵelementStart(0, "div", 3)(1, "mj-flow-toolbar",
|
|
23
|
-
i0.ɵɵlistener("ZoomInClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_ZoomInClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomIn()); })("ZoomOutClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_ZoomOutClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomOut()); })("FitToScreenClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_FitToScreenClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomToFit()); })("AutoLayoutClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_AutoLayoutClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.AutoArrange()); })("GridToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_GridToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onGridToggled($event)); })("MinimapToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_MinimapToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onMinimapToggled($event)); })("LegendToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_LegendToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onLegendToggled($event)); })("PanModeToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_PanModeToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onPanModeToggled($event)); });
|
|
24
|
+
i0.ɵɵelementStart(0, "div", 3)(1, "mj-flow-toolbar", 20);
|
|
25
|
+
i0.ɵɵlistener("ZoomInClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_ZoomInClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomIn()); })("ZoomOutClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_ZoomOutClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomOut()); })("FitToScreenClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_FitToScreenClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.ZoomToFit()); })("AutoLayoutClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_AutoLayoutClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.AutoArrange()); })("GridToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_GridToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onGridToggled($event)); })("MinimapToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_MinimapToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onMinimapToggled($event)); })("LegendToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_LegendToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onLegendToggled($event)); })("PanModeToggled", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_PanModeToggled_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onPanModeToggled($event)); })("MinimizeClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_MinimizeClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SetToolbarVisibility("minimized")); })("HideClicked", function FlowEditorComponent_Conditional_1_Template_mj_flow_toolbar_HideClicked_1_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SetToolbarVisibility("hidden")); });
|
|
24
26
|
i0.ɵɵelementEnd()();
|
|
25
27
|
} if (rf & 2) {
|
|
26
28
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
29
|
+
i0.ɵɵattribute("data-align", ctx_r2.ToolbarAlign);
|
|
27
30
|
i0.ɵɵadvance();
|
|
28
31
|
i0.ɵɵproperty("ZoomLevel", ctx_r2.zoomLevel)("ShowGrid", ctx_r2.ShowGrid)("ShowMinimap", ctx_r2.ShowMinimap)("ShowLegend", ctx_r2.ShowLegend)("ReadOnly", ctx_r2.ReadOnly)("PanMode", ctx_r2.panMode);
|
|
29
32
|
} }
|
|
30
|
-
function
|
|
33
|
+
function FlowEditorComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
31
34
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
32
|
-
i0.ɵɵelementStart(0, "
|
|
33
|
-
i0.ɵɵlistener("
|
|
35
|
+
i0.ɵɵelementStart(0, "button", 21);
|
|
36
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SetToolbarVisibility("shown")); });
|
|
37
|
+
i0.ɵɵelement(1, "i", 22);
|
|
38
|
+
i0.ɵɵelementEnd();
|
|
39
|
+
} if (rf & 2) {
|
|
40
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
41
|
+
i0.ɵɵattribute("data-align", ctx_r2.ToolbarAlign);
|
|
42
|
+
} }
|
|
43
|
+
function FlowEditorComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
44
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
45
|
+
i0.ɵɵelementStart(0, "button", 23);
|
|
46
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SetToolbarVisibility("shown")); });
|
|
47
|
+
i0.ɵɵelement(1, "i", 24);
|
|
48
|
+
i0.ɵɵelementEnd();
|
|
49
|
+
} if (rf & 2) {
|
|
50
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
51
|
+
i0.ɵɵattribute("data-align", ctx_r2.ToolbarAlign);
|
|
52
|
+
} }
|
|
53
|
+
function FlowEditorComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
54
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
55
|
+
i0.ɵɵelementStart(0, "mj-flow-palette", 25);
|
|
56
|
+
i0.ɵɵlistener("NodeTypeActivated", function FlowEditorComponent_Conditional_5_Template_mj_flow_palette_NodeTypeActivated_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onPaletteNodeTypeActivated($event)); });
|
|
34
57
|
i0.ɵɵelementEnd();
|
|
35
58
|
} if (rf & 2) {
|
|
36
59
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
37
60
|
i0.ɵɵproperty("NodeTypes", ctx_r2.NodeTypes);
|
|
38
61
|
} }
|
|
39
|
-
function
|
|
62
|
+
function FlowEditorComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
40
63
|
i0.ɵɵelementStart(0, "f-background");
|
|
41
|
-
i0.ɵɵelement(1, "f-circle-pattern",
|
|
64
|
+
i0.ɵɵelement(1, "f-circle-pattern", 26);
|
|
42
65
|
i0.ɵɵelementEnd();
|
|
43
66
|
} if (rf & 2) {
|
|
44
67
|
i0.ɵɵadvance();
|
|
45
68
|
i0.ɵɵproperty("color", "#94a3b8")("radius", 24);
|
|
46
69
|
} }
|
|
47
|
-
function
|
|
48
|
-
i0.ɵɵelement(0, "f-line-alignment",
|
|
70
|
+
function FlowEditorComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
71
|
+
i0.ɵɵelement(0, "f-line-alignment", 10);
|
|
49
72
|
} if (rf & 2) {
|
|
50
73
|
i0.ɵɵproperty("fAlignThreshold", 10);
|
|
51
74
|
} }
|
|
52
|
-
function
|
|
53
|
-
i0.ɵɵelementStart(0, "f-connection-for-create",
|
|
75
|
+
function FlowEditorComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
76
|
+
i0.ɵɵelementStart(0, "f-connection-for-create", 12);
|
|
54
77
|
i0.ɵɵnamespaceSVG();
|
|
55
|
-
i0.ɵɵelementStart(1, "svg",
|
|
56
|
-
i0.ɵɵelement(2, "path",
|
|
78
|
+
i0.ɵɵelementStart(1, "svg", 27);
|
|
79
|
+
i0.ɵɵelement(2, "path", 28);
|
|
57
80
|
i0.ɵɵelementEnd()();
|
|
58
81
|
} if (rf & 2) {
|
|
59
82
|
i0.ɵɵproperty("fRadius", 8)("fOffset", 12);
|
|
60
83
|
i0.ɵɵadvance();
|
|
61
84
|
i0.ɵɵproperty("refX", 9)("refY", 5)("height", 10)("width", 10);
|
|
62
85
|
} }
|
|
63
|
-
function
|
|
64
|
-
i0.ɵɵelement(0, "i",
|
|
86
|
+
function FlowEditorComponent_For_15_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
i0.ɵɵelement(0, "i", 34);
|
|
65
88
|
} if (rf & 2) {
|
|
66
|
-
const
|
|
67
|
-
i0.ɵɵstyleProp("color",
|
|
68
|
-
i0.ɵɵproperty("ngClass",
|
|
89
|
+
const conn_r8 = i0.ɵɵnextContext(2).$implicit;
|
|
90
|
+
i0.ɵɵstyleProp("color", conn_r8.LabelIconColor || "inherit");
|
|
91
|
+
i0.ɵɵproperty("ngClass", conn_r8.LabelIcon);
|
|
69
92
|
} }
|
|
70
|
-
function
|
|
71
|
-
i0.ɵɵelementStart(0, "div",
|
|
72
|
-
i0.ɵɵconditionalCreate(1,
|
|
93
|
+
function FlowEditorComponent_For_15_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
94
|
+
i0.ɵɵelementStart(0, "div", 32);
|
|
95
|
+
i0.ɵɵconditionalCreate(1, FlowEditorComponent_For_15_Conditional_3_Conditional_1_Template, 1, 3, "i", 33);
|
|
73
96
|
i0.ɵɵtext(2);
|
|
74
97
|
i0.ɵɵelementEnd();
|
|
75
98
|
} if (rf & 2) {
|
|
76
|
-
const
|
|
99
|
+
const conn_r8 = i0.ɵɵnextContext().$implicit;
|
|
77
100
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
78
101
|
i0.ɵɵstyleProp("background-color", ctx_r2.ConnectionLabelBackground)("border-color", ctx_r2.ConnectionLabelBorderColor)("color", ctx_r2.ConnectionLabelTextColor);
|
|
79
|
-
i0.ɵɵproperty("position", 0.5)("title",
|
|
102
|
+
i0.ɵɵproperty("position", 0.5)("title", conn_r8.LabelDetail || conn_r8.Label || "");
|
|
80
103
|
i0.ɵɵadvance();
|
|
81
|
-
i0.ɵɵconditional(
|
|
104
|
+
i0.ɵɵconditional(conn_r8.LabelIcon ? 1 : -1);
|
|
82
105
|
i0.ɵɵadvance();
|
|
83
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
106
|
+
i0.ɵɵtextInterpolate1(" ", conn_r8.Label, " ");
|
|
84
107
|
} }
|
|
85
|
-
function
|
|
86
|
-
const
|
|
87
|
-
i0.ɵɵelementStart(0, "f-connection",
|
|
88
|
-
i0.ɵɵlistener("click", function
|
|
108
|
+
function FlowEditorComponent_For_15_Template(rf, ctx) { if (rf & 1) {
|
|
109
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
110
|
+
i0.ɵɵelementStart(0, "f-connection", 29);
|
|
111
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_For_15_Template_f_connection_click_0_listener($event) { const conn_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onConnectionClicked($event, conn_r8)); })("contextmenu", function FlowEditorComponent_For_15_Template_f_connection_contextmenu_0_listener($event) { const conn_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onConnectionContextMenu($event, conn_r8)); });
|
|
89
112
|
i0.ɵɵnamespaceSVG();
|
|
90
|
-
i0.ɵɵelementStart(1, "svg",
|
|
91
|
-
i0.ɵɵelement(2, "path",
|
|
113
|
+
i0.ɵɵelementStart(1, "svg", 27);
|
|
114
|
+
i0.ɵɵelement(2, "path", 30);
|
|
92
115
|
i0.ɵɵelementEnd();
|
|
93
|
-
i0.ɵɵconditionalCreate(3,
|
|
116
|
+
i0.ɵɵconditionalCreate(3, FlowEditorComponent_For_15_Conditional_3_Template, 3, 10, "div", 31);
|
|
94
117
|
i0.ɵɵelementEnd();
|
|
95
118
|
} if (rf & 2) {
|
|
96
|
-
const
|
|
119
|
+
const conn_r8 = ctx.$implicit;
|
|
97
120
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
98
|
-
i0.ɵɵstyleProp("--connection-color",
|
|
99
|
-
i0.ɵɵclassProp("mj-flow-connection-colored", !!
|
|
100
|
-
i0.ɵɵproperty("fConnectionId",
|
|
121
|
+
i0.ɵɵstyleProp("--connection-color", conn_r8.Color || "#94a3b8")("--connection-width", conn_r8.StrokeWidth || 2, "px");
|
|
122
|
+
i0.ɵɵclassProp("mj-flow-connection-colored", !!conn_r8.Color)("mj-flow-connection-dashed", conn_r8.Style === "dashed")("mj-flow-connection-dotted", conn_r8.Style === "dotted")("mj-flow-connection-animated", !!conn_r8.Animated);
|
|
123
|
+
i0.ɵɵproperty("fConnectionId", conn_r8.ID)("fOutputId", conn_r8.SourcePortID)("fInputId", conn_r8.TargetPortID)("fRadius", 8)("fOffset", 12)("fSelectionDisabled", false)("fReassignDisabled", ctx_r2.ReadOnly);
|
|
101
124
|
i0.ɵɵadvance();
|
|
102
|
-
i0.ɵɵproperty("refX", 9)("refY", 5)("height", 10)("width", 10);
|
|
125
|
+
i0.ɵɵproperty("refX", 9)("refY", 5)("height", conn_r8.Animated ? 16 : 10)("width", conn_r8.Animated ? 16 : 10);
|
|
103
126
|
i0.ɵɵadvance();
|
|
104
|
-
i0.ɵɵattribute("fill",
|
|
127
|
+
i0.ɵɵattribute("fill", conn_r8.Color || "#94a3b8");
|
|
105
128
|
i0.ɵɵadvance();
|
|
106
|
-
i0.ɵɵconditional(
|
|
129
|
+
i0.ɵɵconditional(conn_r8.Label ? 3 : -1);
|
|
107
130
|
} }
|
|
108
|
-
function
|
|
109
|
-
const
|
|
110
|
-
i0.ɵɵelementStart(0, "mj-flow-node",
|
|
111
|
-
i0.ɵɵlistener("contextmenu", function
|
|
131
|
+
function FlowEditorComponent_For_17_Template(rf, ctx) { if (rf & 1) {
|
|
132
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
133
|
+
i0.ɵɵelementStart(0, "mj-flow-node", 35);
|
|
134
|
+
i0.ɵɵlistener("contextmenu", function FlowEditorComponent_For_17_Template_mj_flow_node_contextmenu_0_listener($event) { const node_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onNodeContextMenu($event, node_r10)); });
|
|
112
135
|
i0.ɵɵelementEnd();
|
|
113
136
|
} if (rf & 2) {
|
|
114
|
-
const
|
|
137
|
+
const node_r10 = ctx.$implicit;
|
|
115
138
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
116
|
-
i0.ɵɵproperty("fNodeId",
|
|
139
|
+
i0.ɵɵproperty("fNodeId", node_r10.ID)("fNodePosition", i0.ɵɵpureFunction2(8, _c2, node_r10.Position.X, node_r10.Position.Y))("fNodeDraggingDisabled", ctx_r2.ReadOnly || ctx_r2.panMode || node_r10.Locked === true)("fNodeSelectionDisabled", ctx_r2.panMode)("fConnectOnNode", !ctx_r2.ReadOnly && !ctx_r2.panMode)("Node", node_r10)("TypeConfig", ctx_r2.GetTypeConfig(node_r10.Type))("ReadOnly", ctx_r2.ReadOnly);
|
|
117
140
|
} }
|
|
118
|
-
function
|
|
141
|
+
function FlowEditorComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
119
142
|
i0.ɵɵelement(0, "f-selection-area");
|
|
120
143
|
} }
|
|
121
|
-
function
|
|
122
|
-
i0.ɵɵelementStart(0, "div",
|
|
123
|
-
i0.ɵɵelement(1, "f-minimap",
|
|
144
|
+
function FlowEditorComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
145
|
+
i0.ɵɵelementStart(0, "div", 15);
|
|
146
|
+
i0.ɵɵelement(1, "f-minimap", 36);
|
|
124
147
|
i0.ɵɵelementEnd();
|
|
125
148
|
} if (rf & 2) {
|
|
126
149
|
i0.ɵɵadvance();
|
|
127
150
|
i0.ɵɵproperty("fMinSize", 1500);
|
|
128
151
|
} }
|
|
129
|
-
function
|
|
130
|
-
i0.ɵɵelementStart(0, "div",
|
|
152
|
+
function FlowEditorComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
153
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "div", 37);
|
|
131
154
|
i0.ɵɵtext(2, "Legend");
|
|
132
155
|
i0.ɵɵelementEnd();
|
|
133
|
-
i0.ɵɵelementStart(3, "div",
|
|
156
|
+
i0.ɵɵelementStart(3, "div", 38)(4, "div", 39);
|
|
134
157
|
i0.ɵɵtext(5, "Connections");
|
|
135
158
|
i0.ɵɵelementEnd();
|
|
136
|
-
i0.ɵɵelementStart(6, "div",
|
|
159
|
+
i0.ɵɵelementStart(6, "div", 40);
|
|
137
160
|
i0.ɵɵnamespaceSVG();
|
|
138
|
-
i0.ɵɵelementStart(7, "svg",
|
|
139
|
-
i0.ɵɵelement(8, "line",
|
|
161
|
+
i0.ɵɵelementStart(7, "svg", 41);
|
|
162
|
+
i0.ɵɵelement(8, "line", 42);
|
|
140
163
|
i0.ɵɵelementEnd();
|
|
141
164
|
i0.ɵɵnamespaceHTML();
|
|
142
165
|
i0.ɵɵelementStart(9, "span");
|
|
143
166
|
i0.ɵɵtext(10, "Only exit path");
|
|
144
167
|
i0.ɵɵelementEnd()();
|
|
145
|
-
i0.ɵɵelementStart(11, "div",
|
|
168
|
+
i0.ɵɵelementStart(11, "div", 40);
|
|
146
169
|
i0.ɵɵnamespaceSVG();
|
|
147
|
-
i0.ɵɵelementStart(12, "svg",
|
|
148
|
-
i0.ɵɵelement(13, "line",
|
|
170
|
+
i0.ɵɵelementStart(12, "svg", 41);
|
|
171
|
+
i0.ɵɵelement(13, "line", 43);
|
|
149
172
|
i0.ɵɵelementEnd();
|
|
150
173
|
i0.ɵɵnamespaceHTML();
|
|
151
|
-
i0.ɵɵelement(14, "i",
|
|
174
|
+
i0.ɵɵelement(14, "i", 44);
|
|
152
175
|
i0.ɵɵelementStart(15, "span");
|
|
153
176
|
i0.ɵɵtext(16, "Default (fallback)");
|
|
154
177
|
i0.ɵɵelementEnd()();
|
|
155
|
-
i0.ɵɵelementStart(17, "div",
|
|
178
|
+
i0.ɵɵelementStart(17, "div", 40);
|
|
156
179
|
i0.ɵɵnamespaceSVG();
|
|
157
|
-
i0.ɵɵelementStart(18, "svg",
|
|
158
|
-
i0.ɵɵelement(19, "line",
|
|
180
|
+
i0.ɵɵelementStart(18, "svg", 41);
|
|
181
|
+
i0.ɵɵelement(19, "line", 45);
|
|
159
182
|
i0.ɵɵelementEnd();
|
|
160
183
|
i0.ɵɵnamespaceHTML();
|
|
161
184
|
i0.ɵɵelementStart(20, "span");
|
|
162
185
|
i0.ɵɵtext(21, "Conditional");
|
|
163
186
|
i0.ɵɵelementEnd()();
|
|
164
|
-
i0.ɵɵelementStart(22, "div",
|
|
187
|
+
i0.ɵɵelementStart(22, "div", 40);
|
|
165
188
|
i0.ɵɵnamespaceSVG();
|
|
166
|
-
i0.ɵɵelementStart(23, "svg",
|
|
167
|
-
i0.ɵɵelement(24, "line",
|
|
189
|
+
i0.ɵɵelementStart(23, "svg", 41);
|
|
190
|
+
i0.ɵɵelement(24, "line", 46);
|
|
168
191
|
i0.ɵɵelementEnd();
|
|
169
192
|
i0.ɵɵnamespaceHTML();
|
|
170
|
-
i0.ɵɵelement(25, "i",
|
|
193
|
+
i0.ɵɵelement(25, "i", 47);
|
|
171
194
|
i0.ɵɵelementStart(26, "span");
|
|
172
195
|
i0.ɵɵtext(27, "Duplicate defaults");
|
|
173
196
|
i0.ɵɵelementEnd()()();
|
|
174
|
-
i0.ɵɵelementStart(28, "div",
|
|
197
|
+
i0.ɵɵelementStart(28, "div", 38)(29, "div", 39);
|
|
175
198
|
i0.ɵɵtext(30, "Step Types");
|
|
176
199
|
i0.ɵɵelementEnd();
|
|
177
|
-
i0.ɵɵelementStart(31, "div",
|
|
178
|
-
i0.ɵɵelement(32, "span",
|
|
200
|
+
i0.ɵɵelementStart(31, "div", 40);
|
|
201
|
+
i0.ɵɵelement(32, "span", 48);
|
|
179
202
|
i0.ɵɵelementStart(33, "span");
|
|
180
203
|
i0.ɵɵtext(34, "Action");
|
|
181
204
|
i0.ɵɵelementEnd()();
|
|
182
|
-
i0.ɵɵelementStart(35, "div",
|
|
183
|
-
i0.ɵɵelement(36, "span",
|
|
205
|
+
i0.ɵɵelementStart(35, "div", 40);
|
|
206
|
+
i0.ɵɵelement(36, "span", 49);
|
|
184
207
|
i0.ɵɵelementStart(37, "span");
|
|
185
208
|
i0.ɵɵtext(38, "Prompt");
|
|
186
209
|
i0.ɵɵelementEnd()();
|
|
187
|
-
i0.ɵɵelementStart(39, "div",
|
|
188
|
-
i0.ɵɵelement(40, "span",
|
|
210
|
+
i0.ɵɵelementStart(39, "div", 40);
|
|
211
|
+
i0.ɵɵelement(40, "span", 50);
|
|
189
212
|
i0.ɵɵelementStart(41, "span");
|
|
190
213
|
i0.ɵɵtext(42, "Sub-Agent");
|
|
191
214
|
i0.ɵɵelementEnd()();
|
|
192
|
-
i0.ɵɵelementStart(43, "div",
|
|
193
|
-
i0.ɵɵelement(44, "span",
|
|
215
|
+
i0.ɵɵelementStart(43, "div", 40);
|
|
216
|
+
i0.ɵɵelement(44, "span", 51);
|
|
194
217
|
i0.ɵɵelementStart(45, "span");
|
|
195
218
|
i0.ɵɵtext(46, "For Each");
|
|
196
219
|
i0.ɵɵelementEnd()();
|
|
197
|
-
i0.ɵɵelementStart(47, "div",
|
|
198
|
-
i0.ɵɵelement(48, "span",
|
|
220
|
+
i0.ɵɵelementStart(47, "div", 40);
|
|
221
|
+
i0.ɵɵelement(48, "span", 52);
|
|
199
222
|
i0.ɵɵelementStart(49, "span");
|
|
200
223
|
i0.ɵɵtext(50, "While");
|
|
201
224
|
i0.ɵɵelementEnd()()();
|
|
202
|
-
i0.ɵɵelementStart(51, "div",
|
|
225
|
+
i0.ɵɵelementStart(51, "div", 38)(52, "div", 39);
|
|
203
226
|
i0.ɵɵtext(53, "Borders");
|
|
204
227
|
i0.ɵɵelementEnd();
|
|
205
|
-
i0.ɵɵelementStart(54, "div",
|
|
206
|
-
i0.ɵɵelement(55, "span",
|
|
228
|
+
i0.ɵɵelementStart(54, "div", 40);
|
|
229
|
+
i0.ɵɵelement(55, "span", 53);
|
|
207
230
|
i0.ɵɵelementStart(56, "span");
|
|
208
231
|
i0.ɵɵtext(57, "Start node");
|
|
209
232
|
i0.ɵɵelementEnd()();
|
|
210
|
-
i0.ɵɵelementStart(58, "div",
|
|
211
|
-
i0.ɵɵelement(59, "span",
|
|
233
|
+
i0.ɵɵelementStart(58, "div", 40);
|
|
234
|
+
i0.ɵɵelement(59, "span", 54)(60, "i", 55);
|
|
212
235
|
i0.ɵɵelementStart(61, "span");
|
|
213
236
|
i0.ɵɵtext(62, "Missing config");
|
|
214
237
|
i0.ɵɵelementEnd()()()();
|
|
215
238
|
} }
|
|
216
|
-
function
|
|
217
|
-
i0.ɵɵelementStart(0, "p",
|
|
239
|
+
function FlowEditorComponent_Conditional_21_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
240
|
+
i0.ɵɵelementStart(0, "p", 57);
|
|
218
241
|
i0.ɵɵtext(1, " Or use auto-layout after adding steps to arrange them automatically ");
|
|
219
242
|
i0.ɵɵelementEnd();
|
|
220
243
|
} }
|
|
221
|
-
function
|
|
222
|
-
i0.ɵɵelementStart(0, "div",
|
|
223
|
-
i0.ɵɵconditionalCreate(2,
|
|
244
|
+
function FlowEditorComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
245
|
+
i0.ɵɵelementStart(0, "div", 17)(1, "mj-empty-state", 56);
|
|
246
|
+
i0.ɵɵconditionalCreate(2, FlowEditorComponent_Conditional_21_Conditional_2_Template, 2, 0, "p", 57);
|
|
224
247
|
i0.ɵɵelementEnd()();
|
|
225
248
|
} if (rf & 2) {
|
|
226
249
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -229,33 +252,66 @@ function FlowEditorComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
|
229
252
|
i0.ɵɵadvance();
|
|
230
253
|
i0.ɵɵconditional(!ctx_r2.ReadOnly ? 2 : -1);
|
|
231
254
|
} }
|
|
232
|
-
function
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
i0.ɵɵ
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
i0.ɵɵelementStart(
|
|
240
|
-
i0.ɵɵtext(
|
|
241
|
-
i0.ɵɵelementEnd()
|
|
242
|
-
|
|
243
|
-
i0.ɵɵ
|
|
244
|
-
i0.ɵɵ
|
|
245
|
-
i0.ɵɵ
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
i0.ɵɵ
|
|
255
|
+
function FlowEditorComponent_Conditional_22_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
256
|
+
i0.ɵɵelement(0, "i", 60);
|
|
257
|
+
} if (rf & 2) {
|
|
258
|
+
const item_r13 = i0.ɵɵnextContext().$implicit;
|
|
259
|
+
i0.ɵɵproperty("ngClass", item_r13.Icon);
|
|
260
|
+
} }
|
|
261
|
+
function FlowEditorComponent_Conditional_22_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
262
|
+
i0.ɵɵelementStart(0, "kbd", 61);
|
|
263
|
+
i0.ɵɵtext(1);
|
|
264
|
+
i0.ɵɵelementEnd();
|
|
265
|
+
} if (rf & 2) {
|
|
266
|
+
const item_r13 = i0.ɵɵnextContext().$implicit;
|
|
267
|
+
i0.ɵɵadvance();
|
|
268
|
+
i0.ɵɵtextInterpolate(item_r13.Shortcut);
|
|
269
|
+
} }
|
|
270
|
+
function FlowEditorComponent_Conditional_22_For_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
271
|
+
i0.ɵɵelement(0, "div", 62);
|
|
272
|
+
} }
|
|
273
|
+
function FlowEditorComponent_Conditional_22_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
274
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
275
|
+
i0.ɵɵelementStart(0, "button", 59);
|
|
276
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Conditional_22_For_2_Template_button_click_0_listener() { const item_r13 = i0.ɵɵrestoreView(_r12).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onContextMenuAction(item_r13.ID)); });
|
|
277
|
+
i0.ɵɵconditionalCreate(1, FlowEditorComponent_Conditional_22_For_2_Conditional_1_Template, 1, 1, "i", 60);
|
|
278
|
+
i0.ɵɵelementStart(2, "span");
|
|
279
|
+
i0.ɵɵtext(3);
|
|
280
|
+
i0.ɵɵelementEnd();
|
|
281
|
+
i0.ɵɵconditionalCreate(4, FlowEditorComponent_Conditional_22_For_2_Conditional_4_Template, 2, 1, "kbd", 61);
|
|
282
|
+
i0.ɵɵelementEnd();
|
|
283
|
+
i0.ɵɵconditionalCreate(5, FlowEditorComponent_Conditional_22_For_2_Conditional_5_Template, 1, 0, "div", 62);
|
|
284
|
+
} if (rf & 2) {
|
|
285
|
+
const item_r13 = ctx.$implicit;
|
|
286
|
+
const $index_r14 = ctx.$index;
|
|
287
|
+
const ɵ$index_193_r15 = ctx.$index;
|
|
288
|
+
const ɵ$count_193_r16 = ctx.$count;
|
|
289
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
290
|
+
i0.ɵɵclassProp("mj-flow-context-menu-item--danger", item_r13.Danger);
|
|
291
|
+
i0.ɵɵproperty("disabled", item_r13.Disabled);
|
|
292
|
+
i0.ɵɵadvance();
|
|
293
|
+
i0.ɵɵconditional(item_r13.Icon ? 1 : -1);
|
|
294
|
+
i0.ɵɵadvance(2);
|
|
295
|
+
i0.ɵɵtextInterpolate(item_r13.Label);
|
|
296
|
+
i0.ɵɵadvance();
|
|
297
|
+
i0.ɵɵconditional(item_r13.Shortcut ? 4 : -1);
|
|
298
|
+
i0.ɵɵadvance();
|
|
299
|
+
i0.ɵɵconditional(!(ɵ$index_193_r15 === ɵ$count_193_r16 - 1) && item_r13.Danger !== (ctx_r2.contextMenuItems[$index_r14 + 1] == null ? null : ctx_r2.contextMenuItems[$index_r14 + 1].Danger) ? 5 : -1);
|
|
300
|
+
} }
|
|
301
|
+
function FlowEditorComponent_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
302
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
303
|
+
i0.ɵɵelementStart(0, "div", 58);
|
|
304
|
+
i0.ɵɵlistener("click", function FlowEditorComponent_Conditional_22_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
305
|
+
i0.ɵɵrepeaterCreate(1, FlowEditorComponent_Conditional_22_For_2_Template, 6, 7, null, null, _forTrack0);
|
|
306
|
+
i0.ɵɵelementEnd();
|
|
249
307
|
} if (rf & 2) {
|
|
250
308
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
251
309
|
i0.ɵɵstyleProp("left", ctx_r2.contextMenuX, "px")("top", ctx_r2.contextMenuY, "px");
|
|
252
|
-
i0.ɵɵadvance(
|
|
253
|
-
i0.ɵɵ
|
|
254
|
-
i0.ɵɵadvance(5);
|
|
255
|
-
i0.ɵɵtextInterpolate1("Remove ", ctx_r2.contextMenuTargetType === "node" ? "Node" : "Connection");
|
|
310
|
+
i0.ɵɵadvance();
|
|
311
|
+
i0.ɵɵrepeater(ctx_r2.contextMenuItems);
|
|
256
312
|
} }
|
|
257
|
-
function
|
|
258
|
-
i0.ɵɵelement(0, "mj-flow-status-bar",
|
|
313
|
+
function FlowEditorComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
314
|
+
i0.ɵɵelement(0, "mj-flow-status-bar", 19);
|
|
259
315
|
} if (rf & 2) {
|
|
260
316
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
261
317
|
i0.ɵɵproperty("NodeCount", ctx_r2.Nodes.length)("ConnectionCount", ctx_r2.Connections.length)("SelectedCount", ctx_r2.selectedCount)("ZoomLevel", ctx_r2.zoomLevel);
|
|
@@ -288,7 +344,15 @@ export class FlowEditorComponent {
|
|
|
288
344
|
ShowPalette = true;
|
|
289
345
|
ShowGrid = true;
|
|
290
346
|
ShowStatusBar = true;
|
|
347
|
+
/**
|
|
348
|
+
* Legacy on/off. `false` forces the toolbar fully off (no recover tab). Prefer
|
|
349
|
+
* `ToolbarVisibility` when the host wants shown / minimized / hidden with a way back.
|
|
350
|
+
*/
|
|
291
351
|
ShowToolbar = true;
|
|
352
|
+
/** Full bar, a restore chip, or a recover tab. Ignored when `ShowToolbar` is false. */
|
|
353
|
+
ToolbarVisibility = 'shown';
|
|
354
|
+
/** Left / center / right along the top of the canvas. */
|
|
355
|
+
ToolbarAlign = 'center';
|
|
292
356
|
ShowLegend = true;
|
|
293
357
|
GridSize = 20;
|
|
294
358
|
AutoLayoutDirection = 'vertical';
|
|
@@ -321,9 +385,26 @@ export class FlowEditorComponent {
|
|
|
321
385
|
ConnectionsChanged = new EventEmitter();
|
|
322
386
|
NodeEditRequested = new EventEmitter();
|
|
323
387
|
ConnectionEditRequested = new EventEmitter();
|
|
388
|
+
/** Host may replace `Items` or `Cancel` the menu. Debug attaches here — the canvas stays blind. */
|
|
389
|
+
BeforeContextMenu = new EventEmitter();
|
|
390
|
+
AfterContextMenuAction = new EventEmitter();
|
|
324
391
|
GridToggled = new EventEmitter();
|
|
325
392
|
MinimapToggled = new EventEmitter();
|
|
326
393
|
LegendToggled = new EventEmitter();
|
|
394
|
+
/** The person changed shown / minimized / hidden from the canvas chrome. */
|
|
395
|
+
ToolbarVisibilityChanged = new EventEmitter();
|
|
396
|
+
/** What the template actually paints — `ShowToolbar === false` is a hard hide. */
|
|
397
|
+
get EffectiveToolbarVisibility() {
|
|
398
|
+
return this.ShowToolbar ? this.ToolbarVisibility : 'hidden';
|
|
399
|
+
}
|
|
400
|
+
SetToolbarVisibility(next) {
|
|
401
|
+
if (!this.ShowToolbar)
|
|
402
|
+
return;
|
|
403
|
+
if (this.ToolbarVisibility === next)
|
|
404
|
+
return;
|
|
405
|
+
this.ToolbarVisibility = next;
|
|
406
|
+
this.ToolbarVisibilityChanged.emit(next);
|
|
407
|
+
}
|
|
327
408
|
// ── View Children ───────────────────────────────────────────
|
|
328
409
|
fFlow;
|
|
329
410
|
fCanvas;
|
|
@@ -333,6 +414,11 @@ export class FlowEditorComponent {
|
|
|
333
414
|
zoomLevel = 100;
|
|
334
415
|
canvasPosition = { x: 0, y: 0 };
|
|
335
416
|
canvasScale = 1;
|
|
417
|
+
/** After the first auto-fit, later fLoaded events must not snap the viewport back. */
|
|
418
|
+
hasAutoFitted = false;
|
|
419
|
+
/** True once the person zooms or pans — remounts restore this viewport instead of fitting. */
|
|
420
|
+
viewportOwnedByUser = false;
|
|
421
|
+
applyingProgrammaticViewport = false;
|
|
336
422
|
selectedNodeIDs = [];
|
|
337
423
|
selectedConnectionIDs = [];
|
|
338
424
|
panMode = false;
|
|
@@ -347,6 +433,7 @@ export class FlowEditorComponent {
|
|
|
347
433
|
contextMenuTargetType = 'node';
|
|
348
434
|
contextMenuNode = null;
|
|
349
435
|
contextMenuConnection = null;
|
|
436
|
+
contextMenuItems = [];
|
|
350
437
|
destroy$ = new Subject();
|
|
351
438
|
initialized = false;
|
|
352
439
|
lastConnectionClickTime = 0;
|
|
@@ -371,10 +458,14 @@ export class FlowEditorComponent {
|
|
|
371
458
|
// ── Public Methods ──────────────────────────────────────────
|
|
372
459
|
/** Fit all nodes within the viewport */
|
|
373
460
|
ZoomToFit() {
|
|
461
|
+
this.applyingProgrammaticViewport = true;
|
|
374
462
|
this.fCanvas?.fitToScreen({ x: 150, y: 150 }, true);
|
|
463
|
+
this.hasAutoFitted = true;
|
|
464
|
+
queueMicrotask(() => { this.applyingProgrammaticViewport = false; });
|
|
375
465
|
}
|
|
376
466
|
/** Zoom in one step */
|
|
377
467
|
ZoomIn() {
|
|
468
|
+
this.viewportOwnedByUser = true;
|
|
378
469
|
if (this.fZoom) {
|
|
379
470
|
this.fZoom.zoomIn();
|
|
380
471
|
}
|
|
@@ -386,6 +477,7 @@ export class FlowEditorComponent {
|
|
|
386
477
|
}
|
|
387
478
|
/** Zoom out one step */
|
|
388
479
|
ZoomOut() {
|
|
480
|
+
this.viewportOwnedByUser = true;
|
|
389
481
|
if (this.fZoom) {
|
|
390
482
|
this.fZoom.zoomOut();
|
|
391
483
|
}
|
|
@@ -524,15 +616,29 @@ export class FlowEditorComponent {
|
|
|
524
616
|
// ── Foblex Event Handlers ──────────────────────────────────
|
|
525
617
|
/** Called when Foblex flow finishes loading */
|
|
526
618
|
onFlowLoaded() {
|
|
527
|
-
if (this.Nodes.length
|
|
528
|
-
|
|
619
|
+
if (this.Nodes.length === 0)
|
|
620
|
+
return;
|
|
621
|
+
if (this.viewportOwnedByUser || this.hasAutoFitted) {
|
|
622
|
+
this.restoreViewport();
|
|
623
|
+
return;
|
|
529
624
|
}
|
|
625
|
+
this.hasAutoFitted = true;
|
|
626
|
+
setTimeout(() => this.ZoomToFit(), 200);
|
|
530
627
|
}
|
|
531
628
|
/** Canvas zoom/pan changed */
|
|
532
629
|
onCanvasChange(event) {
|
|
533
630
|
this.canvasPosition = event.position;
|
|
534
631
|
this.canvasScale = event.scale;
|
|
535
632
|
this.updateZoomLevel(event.scale);
|
|
633
|
+
if (!this.applyingProgrammaticViewport)
|
|
634
|
+
this.viewportOwnedByUser = true;
|
|
635
|
+
}
|
|
636
|
+
restoreViewport() {
|
|
637
|
+
if (!this.fCanvas)
|
|
638
|
+
return;
|
|
639
|
+
this.applyingProgrammaticViewport = true;
|
|
640
|
+
this.fCanvas.setScale(this.canvasScale);
|
|
641
|
+
queueMicrotask(() => { this.applyingProgrammaticViewport = false; });
|
|
536
642
|
}
|
|
537
643
|
/** User drew a new connection */
|
|
538
644
|
onCreateConnection(event) {
|
|
@@ -740,11 +846,9 @@ export class FlowEditorComponent {
|
|
|
740
846
|
}
|
|
741
847
|
// ── Context Menu ───────────────────────────────────────────
|
|
742
848
|
onNodeContextMenu(event, node) {
|
|
743
|
-
if (this.ReadOnly)
|
|
744
|
-
return;
|
|
745
849
|
event.preventDefault();
|
|
746
850
|
event.stopPropagation();
|
|
747
|
-
this.
|
|
851
|
+
this.openContextMenu(event, 'node', node, null);
|
|
748
852
|
}
|
|
749
853
|
/** Direct click on a connection — ensures ConnectionSelected fires reliably */
|
|
750
854
|
onConnectionClicked(event, conn) {
|
|
@@ -758,11 +862,9 @@ export class FlowEditorComponent {
|
|
|
758
862
|
this.cdr.detectChanges();
|
|
759
863
|
}
|
|
760
864
|
onConnectionContextMenu(event, conn) {
|
|
761
|
-
if (this.ReadOnly)
|
|
762
|
-
return;
|
|
763
865
|
event.preventDefault();
|
|
764
866
|
event.stopPropagation();
|
|
765
|
-
this.
|
|
867
|
+
this.openContextMenu(event, 'connection', null, conn);
|
|
766
868
|
}
|
|
767
869
|
onContextMenuAction(action) {
|
|
768
870
|
// Capture the target BEFORE closing: hideContextMenu() nulls contextMenuNode and
|
|
@@ -772,7 +874,7 @@ export class FlowEditorComponent {
|
|
|
772
874
|
const node = this.contextMenuNode;
|
|
773
875
|
const connection = this.contextMenuConnection;
|
|
774
876
|
this.hideContextMenu();
|
|
775
|
-
if (action === 'edit') {
|
|
877
|
+
if (!this.ReadOnly && action === 'edit') {
|
|
776
878
|
if (targetType === 'node' && node) {
|
|
777
879
|
this.NodeEditRequested.emit(node);
|
|
778
880
|
}
|
|
@@ -780,7 +882,7 @@ export class FlowEditorComponent {
|
|
|
780
882
|
this.ConnectionEditRequested.emit(connection);
|
|
781
883
|
}
|
|
782
884
|
}
|
|
783
|
-
else if (action === 'remove') {
|
|
885
|
+
else if (!this.ReadOnly && action === 'remove') {
|
|
784
886
|
if (targetType === 'node' && node) {
|
|
785
887
|
this.pushUndoState();
|
|
786
888
|
this.removeNodeById(node.ID);
|
|
@@ -789,19 +891,24 @@ export class FlowEditorComponent {
|
|
|
789
891
|
this.pushUndoState();
|
|
790
892
|
this.removeConnectionById(connection.ID);
|
|
791
893
|
}
|
|
792
|
-
// pushUndoState moved inside the branches: pushing before knowing there IS a target left an
|
|
793
|
-
// undo entry for an action that never happened, so the next Ctrl+Z did nothing visible.
|
|
794
894
|
}
|
|
895
|
+
this.AfterContextMenuAction.emit(new FlowAfterContextMenuActionEventArgs(action, targetType, node, connection));
|
|
795
896
|
}
|
|
796
897
|
onDocumentClick() {
|
|
797
898
|
if (this.contextMenuVisible) {
|
|
798
899
|
this.hideContextMenu();
|
|
799
900
|
}
|
|
800
901
|
}
|
|
801
|
-
|
|
902
|
+
openContextMenu(event, targetType, node, connection) {
|
|
903
|
+
const defaults = this.ReadOnly ? [] : defaultContextMenuItems(targetType);
|
|
904
|
+
const before = new FlowBeforeContextMenuEventArgs(targetType, node, connection, event, defaults);
|
|
905
|
+
this.BeforeContextMenu.emit(before);
|
|
906
|
+
if (before.Cancel || before.Items.length === 0)
|
|
907
|
+
return;
|
|
802
908
|
this.contextMenuTargetType = targetType;
|
|
803
909
|
this.contextMenuNode = node;
|
|
804
910
|
this.contextMenuConnection = connection;
|
|
911
|
+
this.contextMenuItems = before.Items;
|
|
805
912
|
this.contextMenuX = event.clientX;
|
|
806
913
|
this.contextMenuY = event.clientY;
|
|
807
914
|
this.contextMenuVisible = true;
|
|
@@ -985,70 +1092,70 @@ export class FlowEditorComponent {
|
|
|
985
1092
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.canvasArea = _t.first);
|
|
986
1093
|
} }, hostBindings: function FlowEditorComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
987
1094
|
i0.ɵɵlistener("click", function FlowEditorComponent_click_HostBindingHandler() { return ctx.onDocumentClick(); }, i0.ɵɵresolveDocument)("keydown", function FlowEditorComponent_keydown_HostBindingHandler($event) { return ctx.onKeyDown($event); });
|
|
988
|
-
} }, inputs: { Nodes: "Nodes", Connections: "Connections", NodeTypes: "NodeTypes", ReadOnly: "ReadOnly", ShowMinimap: "ShowMinimap", ShowPalette: "ShowPalette", ShowGrid: "ShowGrid", ShowStatusBar: "ShowStatusBar", ShowToolbar: "ShowToolbar", ShowLegend: "ShowLegend", GridSize: "GridSize", AutoLayoutDirection: "AutoLayoutDirection", ConnectionLabelBackground: "ConnectionLabelBackground", ConnectionLabelBorderColor: "ConnectionLabelBorderColor", ConnectionLabelTextColor: "ConnectionLabelTextColor" }, outputs: { NodeSelected: "NodeSelected", NodeAdded: "NodeAdded", NodeRemoved: "NodeRemoved", NodeMoved: "NodeMoved", ConnectionCreated: "ConnectionCreated", ConnectionRemoved: "ConnectionRemoved", ConnectionReassigned: "ConnectionReassigned", ConnectionSelected: "ConnectionSelected", SelectionChanged: "SelectionChanged", CanvasClicked: "CanvasClicked", NodesChanged: "NodesChanged", ConnectionsChanged: "ConnectionsChanged", NodeEditRequested: "NodeEditRequested", ConnectionEditRequested: "ConnectionEditRequested", GridToggled: "GridToggled", MinimapToggled: "MinimapToggled", LegendToggled: "LegendToggled" }, standalone: false, features: [i0.ɵɵProvidersFeature([FlowStateService, FlowLayoutService])], decls:
|
|
1095
|
+
} }, inputs: { Nodes: "Nodes", Connections: "Connections", NodeTypes: "NodeTypes", ReadOnly: "ReadOnly", ShowMinimap: "ShowMinimap", ShowPalette: "ShowPalette", ShowGrid: "ShowGrid", ShowStatusBar: "ShowStatusBar", ShowToolbar: "ShowToolbar", ToolbarVisibility: "ToolbarVisibility", ToolbarAlign: "ToolbarAlign", ShowLegend: "ShowLegend", GridSize: "GridSize", AutoLayoutDirection: "AutoLayoutDirection", ConnectionLabelBackground: "ConnectionLabelBackground", ConnectionLabelBorderColor: "ConnectionLabelBorderColor", ConnectionLabelTextColor: "ConnectionLabelTextColor" }, outputs: { NodeSelected: "NodeSelected", NodeAdded: "NodeAdded", NodeRemoved: "NodeRemoved", NodeMoved: "NodeMoved", ConnectionCreated: "ConnectionCreated", ConnectionRemoved: "ConnectionRemoved", ConnectionReassigned: "ConnectionReassigned", ConnectionSelected: "ConnectionSelected", SelectionChanged: "SelectionChanged", CanvasClicked: "CanvasClicked", NodesChanged: "NodesChanged", ConnectionsChanged: "ConnectionsChanged", NodeEditRequested: "NodeEditRequested", ConnectionEditRequested: "ConnectionEditRequested", BeforeContextMenu: "BeforeContextMenu", AfterContextMenuAction: "AfterContextMenuAction", GridToggled: "GridToggled", MinimapToggled: "MinimapToggled", LegendToggled: "LegendToggled", ToolbarVisibilityChanged: "ToolbarVisibilityChanged" }, standalone: false, features: [i0.ɵɵProvidersFeature([FlowStateService, FlowLayoutService])], decls: 24, vars: 25, consts: [["canvasArea", ""], ["fZoomRef", "fComponent"], ["tabindex", "0", 1, "mj-flow-editor"], [1, "mj-flow-editor-toolbar-area"], ["type", "button", "title", "Show canvas tools", "aria-label", "Show canvas tools", 1, "mj-flow-editor-toolbar-chip"], ["type", "button", "title", "Show canvas tools", "aria-label", "Show canvas tools", 1, "mj-flow-editor-toolbar-tab"], [1, "mj-flow-editor-canvas-area"], [3, "NodeTypes"], [1, "mj-flow-editor-canvas"], ["fDraggable", "", 3, "fLoaded", "fCreateConnection", "fReassignConnection", "fCreateNode", "fSelectionChange", "fMoveNodes", "fDraggableDisabled", "fCanvasMoveTrigger", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], [3, "fAlignThreshold"], ["fZoom", "", 3, "fCanvasChange", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "position", "scale"], ["fType", "bezier", 3, "fRadius", "fOffset"], ["fType", "bezier", "fBehavior", "fixed", 3, "fConnectionId", "fOutputId", "fInputId", "fRadius", "fOffset", "fSelectionDisabled", "fReassignDisabled", "--connection-color", "--connection-width", "mj-flow-connection-colored", "mj-flow-connection-dashed", "mj-flow-connection-dotted", "mj-flow-connection-animated"], ["fNode", "", "fDragHandle", "", 3, "fNodeId", "fNodePosition", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fConnectOnNode", "Node", "TypeConfig", "ReadOnly"], ["fDragBlocker", "", 1, "mj-flow-editor-minimap"], [1, "mj-flow-editor-legend"], [1, "mj-flow-editor-empty"], [1, "mj-flow-context-menu", 3, "left", "top"], [3, "NodeCount", "ConnectionCount", "SelectedCount", "ZoomLevel"], [3, "ZoomInClicked", "ZoomOutClicked", "FitToScreenClicked", "AutoLayoutClicked", "GridToggled", "MinimapToggled", "LegendToggled", "PanModeToggled", "MinimizeClicked", "HideClicked", "ZoomLevel", "ShowGrid", "ShowMinimap", "ShowLegend", "ReadOnly", "PanMode"], ["type", "button", "title", "Show canvas tools", "aria-label", "Show canvas tools", 1, "mj-flow-editor-toolbar-chip", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-wrench"], ["type", "button", "title", "Show canvas tools", "aria-label", "Show canvas tools", 1, "mj-flow-editor-toolbar-tab", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-ellipsis"], [3, "NodeTypeActivated", "NodeTypes"], [3, "color", "radius"], ["viewBox", "0 0 10 10", "fMarker", "", "type", "end", "orient", "auto", 3, "refX", "refY", "height", "width"], ["d", "M0 0L10 5L0 10Z", "fill", "#94a3b8"], ["fType", "bezier", "fBehavior", "fixed", 3, "click", "contextmenu", "fConnectionId", "fOutputId", "fInputId", "fRadius", "fOffset", "fSelectionDisabled", "fReassignDisabled"], ["d", "M0 0L10 5L0 10Z"], ["fConnectionContent", "", 1, "mj-flow-connection-label", 3, "position", "backgroundColor", "borderColor", "color", "title"], ["fConnectionContent", "", 1, "mj-flow-connection-label", 3, "position", "title"], [1, "fa-solid", "mj-flow-connection-label-icon", 3, "ngClass", "color"], [1, "fa-solid", "mj-flow-connection-label-icon", 3, "ngClass"], ["fNode", "", "fDragHandle", "", 3, "contextmenu", "fNodeId", "fNodePosition", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fConnectOnNode", "Node", "TypeConfig", "ReadOnly"], [3, "fMinSize"], [1, "mj-flow-editor-legend-title"], [1, "mj-flow-editor-legend-section"], [1, "mj-flow-editor-legend-heading"], [1, "mj-flow-editor-legend-item"], ["width", "28", "height", "10", 1, "mj-flow-editor-legend-line-svg"], ["x1", "0", "y1", "5", "x2", "28", "y2", "5", "stroke", "#64748b", "stroke-width", "2"], ["x1", "0", "y1", "5", "x2", "28", "y2", "5", "stroke", "#16a34a", "stroke-width", "2"], [1, "fa-solid", "fa-circle-check", 2, "color", "#16a34a", "font-size", "10px"], ["x1", "0", "y1", "5", "x2", "28", "y2", "5", "stroke", "#f59e0b", "stroke-width", "2", "stroke-dasharray", "5 3"], ["x1", "0", "y1", "5", "x2", "28", "y2", "5", "stroke", "#ef4444", "stroke-width", "2"], [1, "fa-solid", "fa-triangle-exclamation", 2, "color", "#ef4444", "font-size", "10px"], [1, "mj-flow-editor-legend-swatch", 2, "background", "#3B82F6"], [1, "mj-flow-editor-legend-swatch", 2, "background", "#8B5CF6"], [1, "mj-flow-editor-legend-swatch", 2, "background", "#10B981"], [1, "mj-flow-editor-legend-swatch", 2, "background", "#F59E0B"], [1, "mj-flow-editor-legend-swatch", 2, "background", "#F97316"], [1, "mj-flow-editor-legend-box", 2, "border-color", "#16a34a", "background", "#f0fdf4"], [1, "mj-flow-editor-legend-box", 2, "border-color", "#ef4444", "background", "#fef2f2"], [1, "fa-solid", "fa-triangle-exclamation", 2, "color", "#ea580c", "font-size", "10px"], ["Icon", "fa-solid fa-diagram-project", 3, "Title"], [1, "mj-flow-editor-empty-subtitle"], [1, "mj-flow-context-menu", 3, "click"], ["type", "button", 1, "mj-flow-context-menu-item", 3, "click", "disabled"], [1, "fa-solid", 3, "ngClass"], [1, "mj-flow-context-menu-shortcut"], [1, "mj-flow-context-menu-divider"]], template: function FlowEditorComponent_Template(rf, ctx) { if (rf & 1) {
|
|
989
1096
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
990
1097
|
i0.ɵɵelementStart(0, "div", 2);
|
|
991
|
-
i0.ɵɵconditionalCreate(1, FlowEditorComponent_Conditional_1_Template, 2,
|
|
992
|
-
i0.ɵɵelementStart(
|
|
993
|
-
i0.ɵɵconditionalCreate(
|
|
994
|
-
i0.ɵɵelementStart(
|
|
995
|
-
i0.ɵɵlistener("fLoaded", function
|
|
996
|
-
i0.ɵɵconditionalCreate(
|
|
997
|
-
i0.ɵɵconditionalCreate(
|
|
998
|
-
i0.ɵɵelementStart(
|
|
999
|
-
i0.ɵɵlistener("fCanvasChange", function
|
|
1000
|
-
i0.ɵɵconditionalCreate(
|
|
1001
|
-
i0.ɵɵrepeaterCreate(
|
|
1002
|
-
i0.ɵɵrepeaterCreate(
|
|
1098
|
+
i0.ɵɵconditionalCreate(1, FlowEditorComponent_Conditional_1_Template, 2, 7, "div", 3)(2, FlowEditorComponent_Conditional_2_Template, 2, 1, "button", 4)(3, FlowEditorComponent_Conditional_3_Template, 2, 1, "button", 5);
|
|
1099
|
+
i0.ɵɵelementStart(4, "div", 6);
|
|
1100
|
+
i0.ɵɵconditionalCreate(5, FlowEditorComponent_Conditional_5_Template, 1, 1, "mj-flow-palette", 7);
|
|
1101
|
+
i0.ɵɵelementStart(6, "div", 8, 0)(8, "f-flow", 9);
|
|
1102
|
+
i0.ɵɵlistener("fLoaded", function FlowEditorComponent_Template_f_flow_fLoaded_8_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFlowLoaded()); })("fCreateConnection", function FlowEditorComponent_Template_f_flow_fCreateConnection_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onCreateConnection($event)); })("fReassignConnection", function FlowEditorComponent_Template_f_flow_fReassignConnection_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onReassignConnection($event)); })("fCreateNode", function FlowEditorComponent_Template_f_flow_fCreateNode_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onCreateNode($event)); })("fSelectionChange", function FlowEditorComponent_Template_f_flow_fSelectionChange_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSelectionChange($event)); })("fMoveNodes", function FlowEditorComponent_Template_f_flow_fMoveNodes_8_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onNodesMoved($event)); });
|
|
1103
|
+
i0.ɵɵconditionalCreate(9, FlowEditorComponent_Conditional_9_Template, 2, 2, "f-background");
|
|
1104
|
+
i0.ɵɵconditionalCreate(10, FlowEditorComponent_Conditional_10_Template, 1, 1, "f-line-alignment", 10);
|
|
1105
|
+
i0.ɵɵelementStart(11, "f-canvas", 11, 1);
|
|
1106
|
+
i0.ɵɵlistener("fCanvasChange", function FlowEditorComponent_Template_f_canvas_fCanvasChange_11_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onCanvasChange($event)); });
|
|
1107
|
+
i0.ɵɵconditionalCreate(13, FlowEditorComponent_Conditional_13_Template, 3, 6, "f-connection-for-create", 12);
|
|
1108
|
+
i0.ɵɵrepeaterCreate(14, FlowEditorComponent_For_15_Template, 4, 25, "f-connection", 13, ctx.trackConnectionById, true);
|
|
1109
|
+
i0.ɵɵrepeaterCreate(16, FlowEditorComponent_For_17_Template, 1, 11, "mj-flow-node", 14, ctx.trackNodeById, true);
|
|
1003
1110
|
i0.ɵɵelementEnd();
|
|
1004
|
-
i0.ɵɵconditionalCreate(
|
|
1005
|
-
i0.ɵɵconditionalCreate(
|
|
1111
|
+
i0.ɵɵconditionalCreate(18, FlowEditorComponent_Conditional_18_Template, 1, 0, "f-selection-area");
|
|
1112
|
+
i0.ɵɵconditionalCreate(19, FlowEditorComponent_Conditional_19_Template, 2, 1, "div", 15);
|
|
1006
1113
|
i0.ɵɵelementEnd();
|
|
1007
|
-
i0.ɵɵconditionalCreate(
|
|
1008
|
-
i0.ɵɵconditionalCreate(
|
|
1114
|
+
i0.ɵɵconditionalCreate(20, FlowEditorComponent_Conditional_20_Template, 63, 0, "div", 16);
|
|
1115
|
+
i0.ɵɵconditionalCreate(21, FlowEditorComponent_Conditional_21_Template, 3, 2, "div", 17);
|
|
1009
1116
|
i0.ɵɵelementEnd()();
|
|
1010
|
-
i0.ɵɵconditionalCreate(
|
|
1011
|
-
i0.ɵɵconditionalCreate(
|
|
1117
|
+
i0.ɵɵconditionalCreate(22, FlowEditorComponent_Conditional_22_Template, 3, 4, "div", 18);
|
|
1118
|
+
i0.ɵɵconditionalCreate(23, FlowEditorComponent_Conditional_23_Template, 1, 4, "mj-flow-status-bar", 19);
|
|
1012
1119
|
i0.ɵɵelementEnd();
|
|
1013
1120
|
} if (rf & 2) {
|
|
1014
1121
|
i0.ɵɵclassProp("mj-flow-editor--readonly", ctx.ReadOnly);
|
|
1015
1122
|
i0.ɵɵadvance();
|
|
1016
|
-
i0.ɵɵconditional(ctx.ShowToolbar ? 1 : -1);
|
|
1017
|
-
i0.ɵɵadvance(
|
|
1018
|
-
i0.ɵɵconditional(ctx.ShowPalette && !ctx.ReadOnly ?
|
|
1123
|
+
i0.ɵɵconditional(ctx.ShowToolbar && ctx.EffectiveToolbarVisibility === "shown" ? 1 : ctx.ShowToolbar && ctx.EffectiveToolbarVisibility === "minimized" ? 2 : ctx.ShowToolbar && ctx.EffectiveToolbarVisibility === "hidden" ? 3 : -1);
|
|
1124
|
+
i0.ɵɵadvance(4);
|
|
1125
|
+
i0.ɵɵconditional(ctx.ShowPalette && !ctx.ReadOnly ? 5 : -1);
|
|
1019
1126
|
i0.ɵɵadvance();
|
|
1020
1127
|
i0.ɵɵclassProp("mj-flow-editor-canvas--pan-mode", ctx.panMode);
|
|
1021
1128
|
i0.ɵɵadvance(2);
|
|
1022
1129
|
i0.ɵɵproperty("fDraggableDisabled", false)("fCanvasMoveTrigger", ctx.canvasMoveTriggerFn)("vCellSize", ctx.GridSize)("hCellSize", ctx.GridSize)("fCellSizeWhileDragging", ctx.ShowGrid);
|
|
1023
1130
|
i0.ɵɵadvance();
|
|
1024
|
-
i0.ɵɵconditional(ctx.ShowGrid ?
|
|
1131
|
+
i0.ɵɵconditional(ctx.ShowGrid ? 9 : -1);
|
|
1025
1132
|
i0.ɵɵadvance();
|
|
1026
|
-
i0.ɵɵconditional(!ctx.ReadOnly ?
|
|
1133
|
+
i0.ɵɵconditional(!ctx.ReadOnly ? 10 : -1);
|
|
1027
1134
|
i0.ɵɵadvance();
|
|
1028
1135
|
i0.ɵɵproperty("fZoomMinimum", 0.15)("fZoomMaximum", 3)("fZoomStep", 0.1)("position", ctx.canvasPosition)("scale", ctx.canvasScale);
|
|
1029
1136
|
i0.ɵɵadvance(2);
|
|
1030
|
-
i0.ɵɵconditional(!ctx.ReadOnly ?
|
|
1137
|
+
i0.ɵɵconditional(!ctx.ReadOnly ? 13 : -1);
|
|
1031
1138
|
i0.ɵɵadvance();
|
|
1032
1139
|
i0.ɵɵrepeater(ctx.Connections);
|
|
1033
1140
|
i0.ɵɵadvance(2);
|
|
1034
1141
|
i0.ɵɵrepeater(ctx.Nodes);
|
|
1035
1142
|
i0.ɵɵadvance(2);
|
|
1036
|
-
i0.ɵɵconditional(!ctx.ReadOnly ?
|
|
1143
|
+
i0.ɵɵconditional(!ctx.ReadOnly ? 18 : -1);
|
|
1037
1144
|
i0.ɵɵadvance();
|
|
1038
|
-
i0.ɵɵconditional(ctx.ShowMinimap ?
|
|
1145
|
+
i0.ɵɵconditional(ctx.ShowMinimap ? 19 : -1);
|
|
1039
1146
|
i0.ɵɵadvance();
|
|
1040
|
-
i0.ɵɵconditional(ctx.ShowLegend && ctx.Nodes.length > 0 ?
|
|
1147
|
+
i0.ɵɵconditional(ctx.ShowLegend && ctx.Nodes.length > 0 ? 20 : -1);
|
|
1041
1148
|
i0.ɵɵadvance();
|
|
1042
|
-
i0.ɵɵconditional(ctx.Nodes.length === 0 ?
|
|
1149
|
+
i0.ɵɵconditional(ctx.Nodes.length === 0 ? 21 : -1);
|
|
1043
1150
|
i0.ɵɵadvance();
|
|
1044
|
-
i0.ɵɵconditional(ctx.contextMenuVisible ?
|
|
1151
|
+
i0.ɵɵconditional(ctx.contextMenuVisible ? 22 : -1);
|
|
1045
1152
|
i0.ɵɵadvance();
|
|
1046
|
-
i0.ɵɵconditional(ctx.ShowStatusBar ?
|
|
1047
|
-
} }, dependencies: [i3.NgClass, i4.FFlowComponent, i4.FCanvasComponent, i4.FBackgroundComponent, i4.FCirclePatternComponent, i4.FZoomDirective, i4.FConnectionContent, i4.FConnectionMarker, i4.FConnectionComponent, i4.FConnectionForCreateComponent, i4.FLineAlignmentComponent, i4.FMinimapComponent, i4.FNodeDirective, i4.FDragHandleDirective, i4.FSelectionAreaComponent, i4.FDragBlockerDirective, i4.FDraggableDirective, i5.MJEmptyStateComponent, i6.FlowNodeComponent, i7.FlowPaletteComponent, i8.FlowToolbarComponent, i9.FlowStatusBarComponent], styles: ["/* ============================================================\n Flow Editor \u2014 Main container styles\n ============================================================ */\n\n.mj-flow-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 400px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n outline: none;\n position: relative;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n.mj-flow-editor--readonly .mj-flow-node-port {\n cursor: default;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Toolbar Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-toolbar-area {\n position: absolute;\n top: 10px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 20;\n}\n\n/* \u2500\u2500 Canvas Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-canvas-area {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-flow-editor-canvas {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.mj-flow-editor-canvas f-flow {\n width: 100%;\n height: 100%;\n}\n\n/* Pan mode \u2014 grab cursor, nodes pass through pointer events to canvas */\n.mj-flow-editor-canvas--pan-mode {\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode:active {\n cursor: grabbing;\n}\n\n.mj-flow-editor-canvas--pan-mode mj-flow-node {\n pointer-events: none;\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode f-connection {\n pointer-events: none;\n}\n\n.mj-flow-editor-canvas--pan-mode .mj-flow-connection-label {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Minimap \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-minimap {\n position: absolute;\n bottom: 12px;\n right: 12px;\n width: 160px;\n height: 120px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n z-index: 15;\n}\n\n.mj-flow-editor-minimap f-minimap {\n width: 100%;\n height: 100%;\n}\n\n/* Foblex minimap SVG node rectangles (no default styles provided by Foblex) */\n.mj-flow-editor-minimap .f-minimap-node {\n fill: var(--mj-border-strong);\n stroke: var(--mj-text-disabled);\n stroke-width: 1;\n rx: 3;\n ry: 3;\n}\n\n.mj-flow-editor-minimap .f-minimap-node.f-selected {\n fill: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n.mj-flow-editor-minimap .f-minimap-group {\n fill: var(--mj-border-default);\n stroke: var(--mj-text-disabled);\n stroke-width: 0.5;\n rx: 2;\n ry: 2;\n}\n\n/* Viewport indicator rectangle */\n.mj-flow-editor-minimap .f-minimap-view {\n fill: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n/* \u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-empty {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 5;\n}\n\n.mj-flow-editor-empty-subtitle {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-disabled);\n margin: 0;\n}\n\n/* \u2500\u2500 Connection Labels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-connection-label {\n display: inline-flex;\n align-items: flex-start;\n gap: 5px;\n background: var(--mj-bg-surface);\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 5px;\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n box-shadow: var(--mj-shadow-sm);\n pointer-events: none;\n line-height: 1.4;\n text-align: center;\n}\n\n.mj-flow-connection-label-icon {\n font-size: 10px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Foblex Overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Canvas \u2014 transparent so the grid pattern shows through */\nf-canvas {\n background: transparent;\n}\n\n/* Selection area */\nf-selection-area {\n --f-selection-area-background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n --f-selection-area-border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n/* Line alignment guides */\nf-line-alignment {\n --f-line-alignment-color: var(--mj-brand-primary);\n}\n\n/* Connection paths \u2014 default stroke color prevents invisible connections */\n.f-connection path {\n stroke: var(--mj-text-disabled);\n stroke-width: 2;\n fill: none;\n transition: stroke 0.15s ease, stroke-width 0.15s ease;\n}\n\n.f-connection:hover path {\n stroke-width: 3;\n}\n\n.f-connection.f-selected path {\n stroke: var(--mj-brand-primary);\n stroke-width: 3;\n}\n\n/* Colored connections use the --connection-color custom property,\n defaulting to neutral when no color is specified by the consumer */\n.mj-flow-connection-colored path {\n stroke: var(--connection-color, var(--mj-text-disabled));\n}\n\n.mj-flow-connection-colored.f-selected path {\n stroke: var(--connection-color, var(--mj-brand-primary));\n stroke-width: 3;\n filter: brightness(0.85);\n}\n\n/* Dashed connection style */\n.mj-flow-connection-dashed path {\n stroke-dasharray: 8 4;\n}\n\n/* Dotted connection style */\n.mj-flow-connection-dotted path {\n stroke-dasharray: 3 3;\n}\n\n/* Connection for create (dragging) */\n.f-connection-for-create path {\n stroke: var(--mj-text-disabled);\n stroke-dasharray: 6 3;\n stroke-width: 2;\n}\n\n/* \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-legend {\n position: absolute;\n bottom: 12px;\n left: 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n backdrop-filter: blur(6px);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 10px 14px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 15;\n font-size: 11px;\n color: var(--mj-text-secondary);\n max-width: 200px;\n}\n\n.mj-flow-editor-legend-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mj-flow-editor-legend-section {\n margin-bottom: 8px;\n}\n\n.mj-flow-editor-legend-section:last-child {\n margin-bottom: 0;\n}\n\n.mj-flow-editor-legend-heading {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 4px;\n}\n\n.mj-flow-editor-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.mj-flow-editor-legend-svg,\n.mj-flow-editor-legend-line-svg {\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-box {\n display: inline-block;\n width: 14px;\n height: 10px;\n border: 2px solid;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n/* \u2500\u2500 Context Menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-context-menu {\n position: fixed;\n min-width: 180px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n padding: 4px;\n z-index: 9999;\n animation: mj-ctx-fade-in 0.1s ease-out;\n}\n\n@keyframes mj-ctx-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.mj-flow-context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n font-size: var(--mj-text-sm);\n font-weight: 450;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: 5px;\n text-align: left;\n transition: background-color 0.1s ease;\n}\n\n.mj-flow-context-menu-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mj-flow-context-menu-item i {\n width: 16px;\n text-align: center;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-item--danger {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-item--danger:hover {\n background-color: var(--mj-status-error-subtle);\n}\n\n.mj-flow-context-menu-item--danger i {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 8px;\n}\n\n/* \u2500\u2500 Focus Indicators (Accessibility) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-toolbar-btn:focus-visible,\n.mj-agent-editor-btn:focus-visible,\n.mj-agent-editor-view-btn:focus-visible,\n.mj-agent-props-close:focus-visible,\n.mj-agent-props-delete-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.mj-flow-palette-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 1px;\n border-radius: var(--mj-radius-md);\n}\n"], encapsulation: 2 });
|
|
1153
|
+
i0.ɵɵconditional(ctx.ShowStatusBar ? 23 : -1);
|
|
1154
|
+
} }, dependencies: [i3.NgClass, i4.FFlowComponent, i4.FCanvasComponent, i4.FBackgroundComponent, i4.FCirclePatternComponent, i4.FZoomDirective, i4.FConnectionContent, i4.FConnectionMarker, i4.FConnectionComponent, i4.FConnectionForCreateComponent, i4.FLineAlignmentComponent, i4.FMinimapComponent, i4.FNodeDirective, i4.FDragHandleDirective, i4.FSelectionAreaComponent, i4.FDragBlockerDirective, i4.FDraggableDirective, i5.MJEmptyStateComponent, i6.FlowNodeComponent, i7.FlowPaletteComponent, i8.FlowToolbarComponent, i9.FlowStatusBarComponent], styles: ["/* ============================================================\n Flow Editor \u2014 Main container styles\n ============================================================ */\n\n/* The HOST is a custom element, which is `display: inline` with auto height until told otherwise.\n Without this, `.mj-flow-editor { height: 100% }` below resolved against an auto-height parent \u2014\n which means auto \u2014 so the canvas fell back to its `min-height` floor and sat at 400px no matter\n how much room its pane actually had.\n\n `height: 100%` here is safe for hosts that DON'T give it a box: it resolves to auto in that case,\n and the floor takes over exactly as before. */\n:host {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.mj-flow-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 400px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n outline: none;\n position: relative;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n.mj-flow-editor--readonly .mj-flow-node-port {\n cursor: default;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Toolbar Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-toolbar-area,\n.mj-flow-editor-toolbar-chip,\n.mj-flow-editor-toolbar-tab {\n position: absolute;\n top: 10px;\n z-index: 20;\n}\n.mj-flow-editor-toolbar-area[data-align=\"center\"],\n.mj-flow-editor-toolbar-chip[data-align=\"center\"],\n.mj-flow-editor-toolbar-tab[data-align=\"center\"] {\n left: 50%;\n transform: translateX(-50%);\n}\n.mj-flow-editor-toolbar-area[data-align=\"left\"],\n.mj-flow-editor-toolbar-chip[data-align=\"left\"],\n.mj-flow-editor-toolbar-tab[data-align=\"left\"] {\n left: 10px;\n}\n.mj-flow-editor-toolbar-area[data-align=\"right\"],\n.mj-flow-editor-toolbar-chip[data-align=\"right\"],\n.mj-flow-editor-toolbar-tab[data-align=\"right\"] {\n right: 10px;\n}\n\n.mj-flow-editor-toolbar-chip,\n.mj-flow-editor-toolbar-tab {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n.mj-flow-editor-toolbar-chip:hover,\n.mj-flow-editor-toolbar-tab:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.mj-flow-editor-toolbar-chip {\n width: 32px;\n height: 32px;\n border-radius: var(--mj-radius-md);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n}\n.mj-flow-editor-toolbar-tab {\n width: 22px;\n height: 18px;\n padding: 0;\n border-radius: var(--mj-radius-sm);\n opacity: 0.55;\n}\n.mj-flow-editor-toolbar-tab:hover { opacity: 1; }\n\n/* \u2500\u2500 Canvas Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-canvas-area {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-flow-editor-canvas {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.mj-flow-editor-canvas f-flow {\n width: 100%;\n height: 100%;\n}\n\n/* Pan mode \u2014 grab cursor, nodes pass through pointer events to canvas */\n.mj-flow-editor-canvas--pan-mode {\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode:active {\n cursor: grabbing;\n}\n\n.mj-flow-editor-canvas--pan-mode mj-flow-node {\n pointer-events: none;\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode f-connection {\n pointer-events: none;\n}\n\n.mj-flow-editor-canvas--pan-mode .mj-flow-connection-label {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Minimap \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-minimap {\n position: absolute;\n bottom: 12px;\n right: 12px;\n width: 160px;\n height: 120px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n z-index: 15;\n}\n\n.mj-flow-editor-minimap f-minimap {\n width: 100%;\n height: 100%;\n}\n\n/* Foblex minimap SVG node rectangles (no default styles provided by Foblex) */\n.mj-flow-editor-minimap .f-minimap-node {\n fill: var(--mj-border-strong);\n stroke: var(--mj-text-disabled);\n stroke-width: 1;\n rx: 3;\n ry: 3;\n}\n\n.mj-flow-editor-minimap .f-minimap-node.f-selected {\n fill: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n.mj-flow-editor-minimap .f-minimap-group {\n fill: var(--mj-border-default);\n stroke: var(--mj-text-disabled);\n stroke-width: 0.5;\n rx: 2;\n ry: 2;\n}\n\n/* Viewport indicator rectangle */\n.mj-flow-editor-minimap .f-minimap-view {\n fill: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n/* \u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-empty {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 5;\n}\n\n.mj-flow-editor-empty-subtitle {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-disabled);\n margin: 0;\n}\n\n/* \u2500\u2500 Connection Labels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-connection-label {\n display: inline-flex;\n align-items: flex-start;\n gap: 5px;\n background: var(--mj-bg-surface);\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 5px;\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n box-shadow: var(--mj-shadow-sm);\n pointer-events: none;\n line-height: 1.4;\n text-align: center;\n}\n\n.mj-flow-connection-label-icon {\n font-size: 10px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Foblex Overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Canvas \u2014 transparent so the grid pattern shows through */\nf-canvas {\n background: transparent;\n}\n\n/* Selection area */\nf-selection-area {\n --f-selection-area-background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n --f-selection-area-border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n/* Line alignment guides */\nf-line-alignment {\n --f-line-alignment-color: var(--mj-brand-primary);\n}\n\n/* Connection paths \u2014 default stroke color prevents invisible connections */\n.f-connection path {\n stroke: var(--mj-text-disabled);\n stroke-width: var(--connection-width, 2px);\n fill: none;\n transition: stroke 0.15s ease, stroke-width 0.15s ease;\n}\n\n.f-connection:hover path {\n stroke-width: calc(var(--connection-width, 2px) + 1px);\n}\n\n.f-connection.f-selected path {\n stroke: var(--mj-brand-primary);\n stroke-width: max(3px, var(--connection-width, 2px));\n}\n\n/* Colored connections use the --connection-color custom property,\n defaulting to neutral when no color is specified by the consumer */\n.mj-flow-connection-colored path {\n stroke: var(--connection-color, var(--mj-text-disabled));\n}\n\n.mj-flow-connection-colored.f-selected path {\n stroke: var(--connection-color, var(--mj-brand-primary));\n stroke-width: max(3px, var(--connection-width, 2px));\n filter: brightness(0.85);\n}\n\n/* Dashed connection style */\n.mj-flow-connection-dashed path {\n stroke-dasharray: 8 4;\n}\n\n/* Dotted connection style */\n.mj-flow-connection-dotted path {\n stroke-dasharray: 3 3;\n}\n\n.mj-flow-connection-animated path {\n stroke-dasharray: 14 10;\n stroke-linecap: round;\n stroke-width: var(--connection-width, 4.5px);\n animation: mj-flow-dash 0.5s linear infinite;\n filter: drop-shadow(0 0 5px color-mix(in srgb, var(--connection-color, var(--mj-brand-primary)) 70%, transparent));\n}\n@keyframes mj-flow-dash {\n to { stroke-dashoffset: -24; }\n}\n\n/* Connection for create (dragging) */\n.f-connection-for-create path {\n stroke: var(--mj-text-disabled);\n stroke-dasharray: 6 3;\n stroke-width: 2;\n}\n\n/* \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-legend {\n position: absolute;\n bottom: 12px;\n left: 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n backdrop-filter: blur(6px);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 10px 14px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 15;\n font-size: 11px;\n color: var(--mj-text-secondary);\n max-width: 200px;\n}\n\n.mj-flow-editor-legend-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mj-flow-editor-legend-section {\n margin-bottom: 8px;\n}\n\n.mj-flow-editor-legend-section:last-child {\n margin-bottom: 0;\n}\n\n.mj-flow-editor-legend-heading {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 4px;\n}\n\n.mj-flow-editor-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.mj-flow-editor-legend-svg,\n.mj-flow-editor-legend-line-svg {\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-box {\n display: inline-block;\n width: 14px;\n height: 10px;\n border: 2px solid;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n/* \u2500\u2500 Context Menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-context-menu {\n position: fixed;\n min-width: 180px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n padding: 4px;\n z-index: 9999;\n animation: mj-ctx-fade-in 0.1s ease-out;\n}\n\n@keyframes mj-ctx-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.mj-flow-context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n font-size: var(--mj-text-sm);\n font-weight: 450;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: 5px;\n text-align: left;\n transition: background-color 0.1s ease;\n}\n\n.mj-flow-context-menu-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mj-flow-context-menu-item i {\n width: 16px;\n text-align: center;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-shortcut {\n margin-left: auto;\n padding: 0 4px;\n border: 1px solid var(--mj-border-default);\n border-radius: 3px;\n font-size: 10px;\n font-family: inherit;\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-item--danger {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-item--danger:hover {\n background-color: var(--mj-status-error-subtle);\n}\n\n.mj-flow-context-menu-item--danger i {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 8px;\n}\n\n/* \u2500\u2500 Focus Indicators (Accessibility) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-toolbar-btn:focus-visible,\n.mj-agent-editor-btn:focus-visible,\n.mj-agent-editor-view-btn:focus-visible,\n.mj-agent-props-close:focus-visible,\n.mj-agent-props-delete-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.mj-flow-palette-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 1px;\n border-radius: var(--mj-radius-md);\n}\n"], encapsulation: 2 });
|
|
1048
1155
|
}
|
|
1049
1156
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(FlowEditorComponent, [{
|
|
1050
1157
|
type: Component,
|
|
1051
|
-
args: [{ standalone: false, selector: 'mj-flow-editor', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, providers: [FlowStateService, FlowLayoutService], template: "<div class=\"mj-flow-editor\" [class.mj-flow-editor--readonly]=\"ReadOnly\" tabindex=\"0\">\n\n <!-- Canvas Toolbar -->\n @if (ShowToolbar) {\n <div class=\"mj-flow-editor-toolbar-area\">\n <mj-flow-toolbar\n [ZoomLevel]=\"zoomLevel\"\n [ShowGrid]=\"ShowGrid\"\n [ShowMinimap]=\"ShowMinimap\"\n [ShowLegend]=\"ShowLegend\"\n [ReadOnly]=\"ReadOnly\"\n [PanMode]=\"panMode\"\n (ZoomInClicked)=\"ZoomIn()\"\n (ZoomOutClicked)=\"ZoomOut()\"\n (FitToScreenClicked)=\"ZoomToFit()\"\n (AutoLayoutClicked)=\"AutoArrange()\"\n (GridToggled)=\"onGridToggled($event)\"\n (MinimapToggled)=\"onMinimapToggled($event)\"\n (LegendToggled)=\"onLegendToggled($event)\"\n (PanModeToggled)=\"onPanModeToggled($event)\">\n </mj-flow-toolbar>\n </div>\n }\n\n <!-- Main Canvas Area -->\n <div class=\"mj-flow-editor-canvas-area\">\n\n <!-- Palette Sidebar -->\n @if (ShowPalette && !ReadOnly) {\n <mj-flow-palette\n [NodeTypes]=\"NodeTypes\"\n (NodeTypeActivated)=\"onPaletteNodeTypeActivated($event)\">\n </mj-flow-palette>\n }\n\n <!-- Foblex Canvas -->\n <div class=\"mj-flow-editor-canvas\" #canvasArea\n [class.mj-flow-editor-canvas--pan-mode]=\"panMode\">\n <f-flow fDraggable\n [fDraggableDisabled]=\"false\"\n [fCanvasMoveTrigger]=\"canvasMoveTriggerFn\"\n [vCellSize]=\"GridSize\"\n [hCellSize]=\"GridSize\"\n [fCellSizeWhileDragging]=\"ShowGrid\"\n (fLoaded)=\"onFlowLoaded()\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n (fMoveNodes)=\"onNodesMoved($event)\">\n\n <!-- Background grid \u2014 MUST be direct child of f-flow (Foblex content projection requires it) -->\n @if (ShowGrid) {\n <f-background>\n <f-circle-pattern [color]=\"'#94a3b8'\" [radius]=\"24\"></f-circle-pattern>\n </f-background>\n }\n\n <!-- Alignment snap lines \u2014 direct child of f-flow -->\n @if (!ReadOnly) {\n <f-line-alignment [fAlignThreshold]=\"10\"></f-line-alignment>\n }\n\n <f-canvas fZoom #fZoomRef=\"fComponent\"\n [fZoomMinimum]=\"0.15\"\n [fZoomMaximum]=\"3\"\n [fZoomStep]=\"0.1\"\n [position]=\"canvasPosition\"\n [scale]=\"canvasScale\"\n (fCanvasChange)=\"onCanvasChange($event)\">\n\n <!-- Interactive connection drawing -->\n @if (!ReadOnly) {\n <f-connection-for-create\n fType=\"bezier\"\n [fRadius]=\"8\"\n [fOffset]=\"12\">\n <svg viewBox=\"0 0 10 10\" fMarker type=\"end\"\n orient=\"auto\" [refX]=\"9\" [refY]=\"5\" [height]=\"10\" [width]=\"10\">\n <path d=\"M0 0L10 5L0 10Z\" fill=\"#94a3b8\"/>\n </svg>\n </f-connection-for-create>\n }\n\n <!-- Connections -->\n @for (conn of Connections; track trackConnectionById($index, conn)) {\n <f-connection\n [fConnectionId]=\"conn.ID\"\n [fOutputId]=\"conn.SourcePortID\"\n [fInputId]=\"conn.TargetPortID\"\n fType=\"bezier\"\n fBehavior=\"fixed\"\n [fRadius]=\"8\"\n [fOffset]=\"12\"\n [fSelectionDisabled]=\"false\"\n [fReassignDisabled]=\"ReadOnly\"\n [style.--connection-color]=\"conn.Color || '#94a3b8'\"\n [class.mj-flow-connection-colored]=\"!!conn.Color\"\n [class.mj-flow-connection-dashed]=\"conn.Style === 'dashed'\"\n [class.mj-flow-connection-dotted]=\"conn.Style === 'dotted'\"\n (click)=\"onConnectionClicked($event, conn)\"\n (contextmenu)=\"onConnectionContextMenu($event, conn)\">\n <!-- Arrow marker -->\n <svg viewBox=\"0 0 10 10\" fMarker type=\"end\"\n orient=\"auto\" [refX]=\"9\" [refY]=\"5\" [height]=\"10\" [width]=\"10\">\n <path d=\"M0 0L10 5L0 10Z\" [attr.fill]=\"conn.Color || '#94a3b8'\"/>\n </svg>\n <!-- Connection label -->\n @if (conn.Label) {\n <div fConnectionContent [position]=\"0.5\"\n class=\"mj-flow-connection-label\"\n [style.backgroundColor]=\"ConnectionLabelBackground\"\n [style.borderColor]=\"ConnectionLabelBorderColor\"\n [style.color]=\"ConnectionLabelTextColor\"\n [title]=\"conn.LabelDetail || conn.Label || ''\">\n @if (conn.LabelIcon) {\n <i\n class=\"fa-solid mj-flow-connection-label-icon\"\n [ngClass]=\"conn.LabelIcon\"\n [style.color]=\"conn.LabelIconColor || 'inherit'\"></i>\n }\n {{ conn.Label }}\n </div>\n }\n </f-connection>\n }\n\n <!-- Nodes -->\n @for (node of Nodes; track trackNodeById($index, node)) {\n <mj-flow-node\n fNode\n fDragHandle\n [fNodeId]=\"node.ID\"\n [fNodePosition]=\"{ x: node.Position.X, y: node.Position.Y }\"\n [fNodeDraggingDisabled]=\"ReadOnly || panMode || node.Locked === true\"\n [fNodeSelectionDisabled]=\"panMode\"\n [fConnectOnNode]=\"!ReadOnly && !panMode\"\n [Node]=\"node\"\n [TypeConfig]=\"GetTypeConfig(node.Type)\"\n [ReadOnly]=\"ReadOnly\"\n (contextmenu)=\"onNodeContextMenu($event, node)\">\n </mj-flow-node>\n }\n\n </f-canvas>\n\n <!-- Rubber-band selection \u2014 direct child of f-flow -->\n @if (!ReadOnly) {\n <f-selection-area></f-selection-area>\n }\n\n <!-- Minimap -->\n @if (ShowMinimap) {\n <div class=\"mj-flow-editor-minimap\" fDragBlocker>\n <f-minimap [fMinSize]=\"1500\"></f-minimap>\n </div>\n }\n </f-flow>\n\n <!-- Legend -->\n @if (ShowLegend && Nodes.length > 0) {\n <div class=\"mj-flow-editor-legend\">\n <div class=\"mj-flow-editor-legend-title\">Legend</div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Connections</div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#64748b\" stroke-width=\"2\"/></svg>\n <span>Only exit path</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#16a34a\" stroke-width=\"2\"/></svg>\n <i class=\"fa-solid fa-circle-check\" style=\"color:#16a34a;font-size:10px;\"></i>\n <span>Default (fallback)</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#f59e0b\" stroke-width=\"2\" stroke-dasharray=\"5 3\"/></svg>\n <span>Conditional</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#ef4444\" stroke-width=\"2\"/></svg>\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color:#ef4444;font-size:10px;\"></i>\n <span>Duplicate defaults</span>\n </div>\n </div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Step Types</div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#3B82F6\"></span>\n <span>Action</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#8B5CF6\"></span>\n <span>Prompt</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#10B981\"></span>\n <span>Sub-Agent</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#F59E0B\"></span>\n <span>For Each</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#F97316\"></span>\n <span>While</span>\n </div>\n </div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Borders</div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-box\" style=\"border-color:#16a34a;background:#f0fdf4;\"></span>\n <span>Start node</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-box\" style=\"border-color:#ef4444;background:#fef2f2;\"></span>\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color:#ea580c;font-size:10px;\"></i>\n <span>Missing config</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Empty state overlay -->\n @if (Nodes.length === 0) {\n <div class=\"mj-flow-editor-empty\">\n <mj-empty-state\n Icon=\"fa-solid fa-diagram-project\"\n [Title]=\"EmptyStateTitle\">\n @if (!ReadOnly) {\n <p class=\"mj-flow-editor-empty-subtitle\">\n Or use auto-layout after adding steps to arrange them automatically\n </p>\n }\n </mj-empty-state>\n </div>\n }\n </div>\n </div>\n\n <!-- Context Menu -->\n @if (contextMenuVisible) {\n <div\n class=\"mj-flow-context-menu\"\n [style.left.px]=\"contextMenuX\"\n [style.top.px]=\"contextMenuY\"\n (click)=\"$event.stopPropagation()\">\n <button class=\"mj-flow-context-menu-item\" (click)=\"onContextMenuAction('edit')\">\n <i class=\"fa-solid fa-pen-to-square\"></i>\n <span>Edit {{ contextMenuTargetType === 'node' ? 'Node' : 'Connection' }}</span>\n </button>\n <div class=\"mj-flow-context-menu-divider\"></div>\n <button class=\"mj-flow-context-menu-item mj-flow-context-menu-item--danger\" (click)=\"onContextMenuAction('remove')\">\n <i class=\"fa-solid fa-trash-can\"></i>\n <span>Remove {{ contextMenuTargetType === 'node' ? 'Node' : 'Connection' }}</span>\n </button>\n </div>\n }\n\n <!-- Status Bar -->\n @if (ShowStatusBar) {\n <mj-flow-status-bar\n [NodeCount]=\"Nodes.length\"\n [ConnectionCount]=\"Connections.length\"\n [SelectedCount]=\"selectedCount\"\n [ZoomLevel]=\"zoomLevel\">\n </mj-flow-status-bar>\n }\n</div>\n", styles: ["/* ============================================================\n Flow Editor \u2014 Main container styles\n ============================================================ */\n\n.mj-flow-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 400px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n outline: none;\n position: relative;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n.mj-flow-editor--readonly .mj-flow-node-port {\n cursor: default;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Toolbar Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-toolbar-area {\n position: absolute;\n top: 10px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 20;\n}\n\n/* \u2500\u2500 Canvas Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-canvas-area {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-flow-editor-canvas {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.mj-flow-editor-canvas f-flow {\n width: 100%;\n height: 100%;\n}\n\n/* Pan mode \u2014 grab cursor, nodes pass through pointer events to canvas */\n.mj-flow-editor-canvas--pan-mode {\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode:active {\n cursor: grabbing;\n}\n\n.mj-flow-editor-canvas--pan-mode mj-flow-node {\n pointer-events: none;\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode f-connection {\n pointer-events: none;\n}\n\n.mj-flow-editor-canvas--pan-mode .mj-flow-connection-label {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Minimap \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-minimap {\n position: absolute;\n bottom: 12px;\n right: 12px;\n width: 160px;\n height: 120px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n z-index: 15;\n}\n\n.mj-flow-editor-minimap f-minimap {\n width: 100%;\n height: 100%;\n}\n\n/* Foblex minimap SVG node rectangles (no default styles provided by Foblex) */\n.mj-flow-editor-minimap .f-minimap-node {\n fill: var(--mj-border-strong);\n stroke: var(--mj-text-disabled);\n stroke-width: 1;\n rx: 3;\n ry: 3;\n}\n\n.mj-flow-editor-minimap .f-minimap-node.f-selected {\n fill: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n.mj-flow-editor-minimap .f-minimap-group {\n fill: var(--mj-border-default);\n stroke: var(--mj-text-disabled);\n stroke-width: 0.5;\n rx: 2;\n ry: 2;\n}\n\n/* Viewport indicator rectangle */\n.mj-flow-editor-minimap .f-minimap-view {\n fill: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n/* \u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-empty {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 5;\n}\n\n.mj-flow-editor-empty-subtitle {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-disabled);\n margin: 0;\n}\n\n/* \u2500\u2500 Connection Labels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-connection-label {\n display: inline-flex;\n align-items: flex-start;\n gap: 5px;\n background: var(--mj-bg-surface);\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 5px;\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n box-shadow: var(--mj-shadow-sm);\n pointer-events: none;\n line-height: 1.4;\n text-align: center;\n}\n\n.mj-flow-connection-label-icon {\n font-size: 10px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Foblex Overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Canvas \u2014 transparent so the grid pattern shows through */\nf-canvas {\n background: transparent;\n}\n\n/* Selection area */\nf-selection-area {\n --f-selection-area-background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n --f-selection-area-border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n/* Line alignment guides */\nf-line-alignment {\n --f-line-alignment-color: var(--mj-brand-primary);\n}\n\n/* Connection paths \u2014 default stroke color prevents invisible connections */\n.f-connection path {\n stroke: var(--mj-text-disabled);\n stroke-width: 2;\n fill: none;\n transition: stroke 0.15s ease, stroke-width 0.15s ease;\n}\n\n.f-connection:hover path {\n stroke-width: 3;\n}\n\n.f-connection.f-selected path {\n stroke: var(--mj-brand-primary);\n stroke-width: 3;\n}\n\n/* Colored connections use the --connection-color custom property,\n defaulting to neutral when no color is specified by the consumer */\n.mj-flow-connection-colored path {\n stroke: var(--connection-color, var(--mj-text-disabled));\n}\n\n.mj-flow-connection-colored.f-selected path {\n stroke: var(--connection-color, var(--mj-brand-primary));\n stroke-width: 3;\n filter: brightness(0.85);\n}\n\n/* Dashed connection style */\n.mj-flow-connection-dashed path {\n stroke-dasharray: 8 4;\n}\n\n/* Dotted connection style */\n.mj-flow-connection-dotted path {\n stroke-dasharray: 3 3;\n}\n\n/* Connection for create (dragging) */\n.f-connection-for-create path {\n stroke: var(--mj-text-disabled);\n stroke-dasharray: 6 3;\n stroke-width: 2;\n}\n\n/* \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-legend {\n position: absolute;\n bottom: 12px;\n left: 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n backdrop-filter: blur(6px);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 10px 14px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 15;\n font-size: 11px;\n color: var(--mj-text-secondary);\n max-width: 200px;\n}\n\n.mj-flow-editor-legend-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mj-flow-editor-legend-section {\n margin-bottom: 8px;\n}\n\n.mj-flow-editor-legend-section:last-child {\n margin-bottom: 0;\n}\n\n.mj-flow-editor-legend-heading {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 4px;\n}\n\n.mj-flow-editor-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.mj-flow-editor-legend-svg,\n.mj-flow-editor-legend-line-svg {\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-box {\n display: inline-block;\n width: 14px;\n height: 10px;\n border: 2px solid;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n/* \u2500\u2500 Context Menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-context-menu {\n position: fixed;\n min-width: 180px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n padding: 4px;\n z-index: 9999;\n animation: mj-ctx-fade-in 0.1s ease-out;\n}\n\n@keyframes mj-ctx-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.mj-flow-context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n font-size: var(--mj-text-sm);\n font-weight: 450;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: 5px;\n text-align: left;\n transition: background-color 0.1s ease;\n}\n\n.mj-flow-context-menu-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mj-flow-context-menu-item i {\n width: 16px;\n text-align: center;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-item--danger {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-item--danger:hover {\n background-color: var(--mj-status-error-subtle);\n}\n\n.mj-flow-context-menu-item--danger i {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 8px;\n}\n\n/* \u2500\u2500 Focus Indicators (Accessibility) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-toolbar-btn:focus-visible,\n.mj-agent-editor-btn:focus-visible,\n.mj-agent-editor-view-btn:focus-visible,\n.mj-agent-props-close:focus-visible,\n.mj-agent-props-delete-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.mj-flow-palette-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 1px;\n border-radius: var(--mj-radius-md);\n}\n"] }]
|
|
1158
|
+
args: [{ standalone: false, selector: 'mj-flow-editor', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, providers: [FlowStateService, FlowLayoutService], template: "<div class=\"mj-flow-editor\" [class.mj-flow-editor--readonly]=\"ReadOnly\" tabindex=\"0\">\n\n <!-- Canvas Toolbar \u2014 shown / minimized / hidden (recover tab). Align is left/center/right. -->\n @if (ShowToolbar && EffectiveToolbarVisibility === 'shown') {\n <div class=\"mj-flow-editor-toolbar-area\" [attr.data-align]=\"ToolbarAlign\">\n <mj-flow-toolbar\n [ZoomLevel]=\"zoomLevel\"\n [ShowGrid]=\"ShowGrid\"\n [ShowMinimap]=\"ShowMinimap\"\n [ShowLegend]=\"ShowLegend\"\n [ReadOnly]=\"ReadOnly\"\n [PanMode]=\"panMode\"\n (ZoomInClicked)=\"ZoomIn()\"\n (ZoomOutClicked)=\"ZoomOut()\"\n (FitToScreenClicked)=\"ZoomToFit()\"\n (AutoLayoutClicked)=\"AutoArrange()\"\n (GridToggled)=\"onGridToggled($event)\"\n (MinimapToggled)=\"onMinimapToggled($event)\"\n (LegendToggled)=\"onLegendToggled($event)\"\n (PanModeToggled)=\"onPanModeToggled($event)\"\n (MinimizeClicked)=\"SetToolbarVisibility('minimized')\"\n (HideClicked)=\"SetToolbarVisibility('hidden')\">\n </mj-flow-toolbar>\n </div>\n } @else if (ShowToolbar && EffectiveToolbarVisibility === 'minimized') {\n <button type=\"button\" class=\"mj-flow-editor-toolbar-chip\" [attr.data-align]=\"ToolbarAlign\"\n (click)=\"SetToolbarVisibility('shown')\"\n title=\"Show canvas tools\" aria-label=\"Show canvas tools\">\n <i class=\"fa-solid fa-wrench\" aria-hidden=\"true\"></i>\n </button>\n } @else if (ShowToolbar && EffectiveToolbarVisibility === 'hidden') {\n <button type=\"button\" class=\"mj-flow-editor-toolbar-tab\" [attr.data-align]=\"ToolbarAlign\"\n (click)=\"SetToolbarVisibility('shown')\"\n title=\"Show canvas tools\" aria-label=\"Show canvas tools\">\n <i class=\"fa-solid fa-ellipsis\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Main Canvas Area -->\n <div class=\"mj-flow-editor-canvas-area\">\n\n <!-- Palette Sidebar -->\n @if (ShowPalette && !ReadOnly) {\n <mj-flow-palette\n [NodeTypes]=\"NodeTypes\"\n (NodeTypeActivated)=\"onPaletteNodeTypeActivated($event)\">\n </mj-flow-palette>\n }\n\n <!-- Foblex Canvas -->\n <div class=\"mj-flow-editor-canvas\" #canvasArea\n [class.mj-flow-editor-canvas--pan-mode]=\"panMode\">\n <f-flow fDraggable\n [fDraggableDisabled]=\"false\"\n [fCanvasMoveTrigger]=\"canvasMoveTriggerFn\"\n [vCellSize]=\"GridSize\"\n [hCellSize]=\"GridSize\"\n [fCellSizeWhileDragging]=\"ShowGrid\"\n (fLoaded)=\"onFlowLoaded()\"\n (fCreateConnection)=\"onCreateConnection($event)\"\n (fReassignConnection)=\"onReassignConnection($event)\"\n (fCreateNode)=\"onCreateNode($event)\"\n (fSelectionChange)=\"onSelectionChange($event)\"\n (fMoveNodes)=\"onNodesMoved($event)\">\n\n <!-- Background grid \u2014 MUST be direct child of f-flow (Foblex content projection requires it) -->\n @if (ShowGrid) {\n <f-background>\n <f-circle-pattern [color]=\"'#94a3b8'\" [radius]=\"24\"></f-circle-pattern>\n </f-background>\n }\n\n <!-- Alignment snap lines \u2014 direct child of f-flow -->\n @if (!ReadOnly) {\n <f-line-alignment [fAlignThreshold]=\"10\"></f-line-alignment>\n }\n\n <f-canvas fZoom #fZoomRef=\"fComponent\"\n [fZoomMinimum]=\"0.15\"\n [fZoomMaximum]=\"3\"\n [fZoomStep]=\"0.1\"\n [position]=\"canvasPosition\"\n [scale]=\"canvasScale\"\n (fCanvasChange)=\"onCanvasChange($event)\">\n\n <!-- Interactive connection drawing -->\n @if (!ReadOnly) {\n <f-connection-for-create\n fType=\"bezier\"\n [fRadius]=\"8\"\n [fOffset]=\"12\">\n <svg viewBox=\"0 0 10 10\" fMarker type=\"end\"\n orient=\"auto\" [refX]=\"9\" [refY]=\"5\" [height]=\"10\" [width]=\"10\">\n <path d=\"M0 0L10 5L0 10Z\" fill=\"#94a3b8\"/>\n </svg>\n </f-connection-for-create>\n }\n\n <!-- Connections -->\n @for (conn of Connections; track trackConnectionById($index, conn)) {\n <f-connection\n [fConnectionId]=\"conn.ID\"\n [fOutputId]=\"conn.SourcePortID\"\n [fInputId]=\"conn.TargetPortID\"\n fType=\"bezier\"\n fBehavior=\"fixed\"\n [fRadius]=\"8\"\n [fOffset]=\"12\"\n [fSelectionDisabled]=\"false\"\n [fReassignDisabled]=\"ReadOnly\"\n [style.--connection-color]=\"conn.Color || '#94a3b8'\"\n [style.--connection-width.px]=\"conn.StrokeWidth || 2\"\n [class.mj-flow-connection-colored]=\"!!conn.Color\"\n [class.mj-flow-connection-dashed]=\"conn.Style === 'dashed'\"\n [class.mj-flow-connection-dotted]=\"conn.Style === 'dotted'\"\n [class.mj-flow-connection-animated]=\"!!conn.Animated\"\n (click)=\"onConnectionClicked($event, conn)\"\n (contextmenu)=\"onConnectionContextMenu($event, conn)\">\n <!-- Arrow marker -->\n <svg viewBox=\"0 0 10 10\" fMarker type=\"end\"\n orient=\"auto\" [refX]=\"9\" [refY]=\"5\"\n [height]=\"conn.Animated ? 16 : 10\"\n [width]=\"conn.Animated ? 16 : 10\">\n <path d=\"M0 0L10 5L0 10Z\" [attr.fill]=\"conn.Color || '#94a3b8'\"/>\n </svg>\n <!-- Connection label -->\n @if (conn.Label) {\n <div fConnectionContent [position]=\"0.5\"\n class=\"mj-flow-connection-label\"\n [style.backgroundColor]=\"ConnectionLabelBackground\"\n [style.borderColor]=\"ConnectionLabelBorderColor\"\n [style.color]=\"ConnectionLabelTextColor\"\n [title]=\"conn.LabelDetail || conn.Label || ''\">\n @if (conn.LabelIcon) {\n <i\n class=\"fa-solid mj-flow-connection-label-icon\"\n [ngClass]=\"conn.LabelIcon\"\n [style.color]=\"conn.LabelIconColor || 'inherit'\"></i>\n }\n {{ conn.Label }}\n </div>\n }\n </f-connection>\n }\n\n <!-- Nodes -->\n @for (node of Nodes; track trackNodeById($index, node)) {\n <mj-flow-node\n fNode\n fDragHandle\n [fNodeId]=\"node.ID\"\n [fNodePosition]=\"{ x: node.Position.X, y: node.Position.Y }\"\n [fNodeDraggingDisabled]=\"ReadOnly || panMode || node.Locked === true\"\n [fNodeSelectionDisabled]=\"panMode\"\n [fConnectOnNode]=\"!ReadOnly && !panMode\"\n [Node]=\"node\"\n [TypeConfig]=\"GetTypeConfig(node.Type)\"\n [ReadOnly]=\"ReadOnly\"\n (contextmenu)=\"onNodeContextMenu($event, node)\">\n </mj-flow-node>\n }\n\n </f-canvas>\n\n <!-- Rubber-band selection \u2014 direct child of f-flow -->\n @if (!ReadOnly) {\n <f-selection-area></f-selection-area>\n }\n\n <!-- Minimap -->\n @if (ShowMinimap) {\n <div class=\"mj-flow-editor-minimap\" fDragBlocker>\n <f-minimap [fMinSize]=\"1500\"></f-minimap>\n </div>\n }\n </f-flow>\n\n <!-- Legend -->\n @if (ShowLegend && Nodes.length > 0) {\n <div class=\"mj-flow-editor-legend\">\n <div class=\"mj-flow-editor-legend-title\">Legend</div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Connections</div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#64748b\" stroke-width=\"2\"/></svg>\n <span>Only exit path</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#16a34a\" stroke-width=\"2\"/></svg>\n <i class=\"fa-solid fa-circle-check\" style=\"color:#16a34a;font-size:10px;\"></i>\n <span>Default (fallback)</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#f59e0b\" stroke-width=\"2\" stroke-dasharray=\"5 3\"/></svg>\n <span>Conditional</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <svg class=\"mj-flow-editor-legend-line-svg\" width=\"28\" height=\"10\"><line x1=\"0\" y1=\"5\" x2=\"28\" y2=\"5\" stroke=\"#ef4444\" stroke-width=\"2\"/></svg>\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color:#ef4444;font-size:10px;\"></i>\n <span>Duplicate defaults</span>\n </div>\n </div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Step Types</div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#3B82F6\"></span>\n <span>Action</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#8B5CF6\"></span>\n <span>Prompt</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#10B981\"></span>\n <span>Sub-Agent</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#F59E0B\"></span>\n <span>For Each</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-swatch\" style=\"background:#F97316\"></span>\n <span>While</span>\n </div>\n </div>\n <div class=\"mj-flow-editor-legend-section\">\n <div class=\"mj-flow-editor-legend-heading\">Borders</div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-box\" style=\"border-color:#16a34a;background:#f0fdf4;\"></span>\n <span>Start node</span>\n </div>\n <div class=\"mj-flow-editor-legend-item\">\n <span class=\"mj-flow-editor-legend-box\" style=\"border-color:#ef4444;background:#fef2f2;\"></span>\n <i class=\"fa-solid fa-triangle-exclamation\" style=\"color:#ea580c;font-size:10px;\"></i>\n <span>Missing config</span>\n </div>\n </div>\n </div>\n }\n\n <!-- Empty state overlay -->\n @if (Nodes.length === 0) {\n <div class=\"mj-flow-editor-empty\">\n <mj-empty-state\n Icon=\"fa-solid fa-diagram-project\"\n [Title]=\"EmptyStateTitle\">\n @if (!ReadOnly) {\n <p class=\"mj-flow-editor-empty-subtitle\">\n Or use auto-layout after adding steps to arrange them automatically\n </p>\n }\n </mj-empty-state>\n </div>\n }\n </div>\n </div>\n\n <!-- Context Menu -->\n @if (contextMenuVisible) {\n <div\n class=\"mj-flow-context-menu\"\n [style.left.px]=\"contextMenuX\"\n [style.top.px]=\"contextMenuY\"\n (click)=\"$event.stopPropagation()\">\n @for (item of contextMenuItems; track item.ID; let last = $last) {\n <button type=\"button\" class=\"mj-flow-context-menu-item\"\n [class.mj-flow-context-menu-item--danger]=\"item.Danger\"\n [disabled]=\"item.Disabled\"\n (click)=\"onContextMenuAction(item.ID)\">\n @if (item.Icon) {\n <i class=\"fa-solid\" [ngClass]=\"item.Icon\"></i>\n }\n <span>{{ item.Label }}</span>\n @if (item.Shortcut) {\n <kbd class=\"mj-flow-context-menu-shortcut\">{{ item.Shortcut }}</kbd>\n }\n </button>\n @if (!last && item.Danger !== contextMenuItems[$index + 1]?.Danger) {\n <div class=\"mj-flow-context-menu-divider\"></div>\n }\n }\n </div>\n }\n\n <!-- Status Bar -->\n @if (ShowStatusBar) {\n <mj-flow-status-bar\n [NodeCount]=\"Nodes.length\"\n [ConnectionCount]=\"Connections.length\"\n [SelectedCount]=\"selectedCount\"\n [ZoomLevel]=\"zoomLevel\">\n </mj-flow-status-bar>\n }\n</div>\n", styles: ["/* ============================================================\n Flow Editor \u2014 Main container styles\n ============================================================ */\n\n/* The HOST is a custom element, which is `display: inline` with auto height until told otherwise.\n Without this, `.mj-flow-editor { height: 100% }` below resolved against an auto-height parent \u2014\n which means auto \u2014 so the canvas fell back to its `min-height` floor and sat at 400px no matter\n how much room its pane actually had.\n\n `height: 100%` here is safe for hosts that DON'T give it a box: it resolves to auto in that case,\n and the floor takes over exactly as before. */\n:host {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.mj-flow-editor {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 400px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n outline: none;\n position: relative;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n}\n\n.mj-flow-editor--readonly .mj-flow-node-port {\n cursor: default;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Toolbar Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-toolbar-area,\n.mj-flow-editor-toolbar-chip,\n.mj-flow-editor-toolbar-tab {\n position: absolute;\n top: 10px;\n z-index: 20;\n}\n.mj-flow-editor-toolbar-area[data-align=\"center\"],\n.mj-flow-editor-toolbar-chip[data-align=\"center\"],\n.mj-flow-editor-toolbar-tab[data-align=\"center\"] {\n left: 50%;\n transform: translateX(-50%);\n}\n.mj-flow-editor-toolbar-area[data-align=\"left\"],\n.mj-flow-editor-toolbar-chip[data-align=\"left\"],\n.mj-flow-editor-toolbar-tab[data-align=\"left\"] {\n left: 10px;\n}\n.mj-flow-editor-toolbar-area[data-align=\"right\"],\n.mj-flow-editor-toolbar-chip[data-align=\"right\"],\n.mj-flow-editor-toolbar-tab[data-align=\"right\"] {\n right: 10px;\n}\n\n.mj-flow-editor-toolbar-chip,\n.mj-flow-editor-toolbar-tab {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-elevated);\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n.mj-flow-editor-toolbar-chip:hover,\n.mj-flow-editor-toolbar-tab:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n.mj-flow-editor-toolbar-chip {\n width: 32px;\n height: 32px;\n border-radius: var(--mj-radius-md);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\n}\n.mj-flow-editor-toolbar-tab {\n width: 22px;\n height: 18px;\n padding: 0;\n border-radius: var(--mj-radius-sm);\n opacity: 0.55;\n}\n.mj-flow-editor-toolbar-tab:hover { opacity: 1; }\n\n/* \u2500\u2500 Canvas Area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-canvas-area {\n display: flex;\n flex: 1;\n overflow: hidden;\n position: relative;\n}\n\n.mj-flow-editor-canvas {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.mj-flow-editor-canvas f-flow {\n width: 100%;\n height: 100%;\n}\n\n/* Pan mode \u2014 grab cursor, nodes pass through pointer events to canvas */\n.mj-flow-editor-canvas--pan-mode {\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode:active {\n cursor: grabbing;\n}\n\n.mj-flow-editor-canvas--pan-mode mj-flow-node {\n pointer-events: none;\n cursor: grab;\n}\n\n.mj-flow-editor-canvas--pan-mode f-connection {\n pointer-events: none;\n}\n\n.mj-flow-editor-canvas--pan-mode .mj-flow-connection-label {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Minimap \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-minimap {\n position: absolute;\n bottom: 12px;\n right: 12px;\n width: 160px;\n height: 120px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n z-index: 15;\n}\n\n.mj-flow-editor-minimap f-minimap {\n width: 100%;\n height: 100%;\n}\n\n/* Foblex minimap SVG node rectangles (no default styles provided by Foblex) */\n.mj-flow-editor-minimap .f-minimap-node {\n fill: var(--mj-border-strong);\n stroke: var(--mj-text-disabled);\n stroke-width: 1;\n rx: 3;\n ry: 3;\n}\n\n.mj-flow-editor-minimap .f-minimap-node.f-selected {\n fill: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n.mj-flow-editor-minimap .f-minimap-group {\n fill: var(--mj-border-default);\n stroke: var(--mj-text-disabled);\n stroke-width: 0.5;\n rx: 2;\n ry: 2;\n}\n\n/* Viewport indicator rectangle */\n.mj-flow-editor-minimap .f-minimap-view {\n fill: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n stroke: var(--mj-brand-primary);\n stroke-width: 1.5;\n}\n\n/* \u2500\u2500 Empty State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-empty {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 5;\n}\n\n.mj-flow-editor-empty-subtitle {\n font-size: var(--mj-text-sm);\n color: var(--mj-text-disabled);\n margin: 0;\n}\n\n/* \u2500\u2500 Connection Labels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-connection-label {\n display: inline-flex;\n align-items: flex-start;\n gap: 5px;\n background: var(--mj-bg-surface);\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 5px;\n padding: 4px 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n box-shadow: var(--mj-shadow-sm);\n pointer-events: none;\n line-height: 1.4;\n text-align: center;\n}\n\n.mj-flow-connection-label-icon {\n font-size: 10px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n/* \u2500\u2500 Foblex Overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* Canvas \u2014 transparent so the grid pattern shows through */\nf-canvas {\n background: transparent;\n}\n\n/* Selection area */\nf-selection-area {\n --f-selection-area-background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n --f-selection-area-border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n/* Line alignment guides */\nf-line-alignment {\n --f-line-alignment-color: var(--mj-brand-primary);\n}\n\n/* Connection paths \u2014 default stroke color prevents invisible connections */\n.f-connection path {\n stroke: var(--mj-text-disabled);\n stroke-width: var(--connection-width, 2px);\n fill: none;\n transition: stroke 0.15s ease, stroke-width 0.15s ease;\n}\n\n.f-connection:hover path {\n stroke-width: calc(var(--connection-width, 2px) + 1px);\n}\n\n.f-connection.f-selected path {\n stroke: var(--mj-brand-primary);\n stroke-width: max(3px, var(--connection-width, 2px));\n}\n\n/* Colored connections use the --connection-color custom property,\n defaulting to neutral when no color is specified by the consumer */\n.mj-flow-connection-colored path {\n stroke: var(--connection-color, var(--mj-text-disabled));\n}\n\n.mj-flow-connection-colored.f-selected path {\n stroke: var(--connection-color, var(--mj-brand-primary));\n stroke-width: max(3px, var(--connection-width, 2px));\n filter: brightness(0.85);\n}\n\n/* Dashed connection style */\n.mj-flow-connection-dashed path {\n stroke-dasharray: 8 4;\n}\n\n/* Dotted connection style */\n.mj-flow-connection-dotted path {\n stroke-dasharray: 3 3;\n}\n\n.mj-flow-connection-animated path {\n stroke-dasharray: 14 10;\n stroke-linecap: round;\n stroke-width: var(--connection-width, 4.5px);\n animation: mj-flow-dash 0.5s linear infinite;\n filter: drop-shadow(0 0 5px color-mix(in srgb, var(--connection-color, var(--mj-brand-primary)) 70%, transparent));\n}\n@keyframes mj-flow-dash {\n to { stroke-dashoffset: -24; }\n}\n\n/* Connection for create (dragging) */\n.f-connection-for-create path {\n stroke: var(--mj-text-disabled);\n stroke-dasharray: 6 3;\n stroke-width: 2;\n}\n\n/* \u2500\u2500 Legend \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-editor-legend {\n position: absolute;\n bottom: 12px;\n left: 12px;\n background: color-mix(in srgb, var(--mj-bg-surface) 92%, transparent);\n backdrop-filter: blur(6px);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 10px 14px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 15;\n font-size: 11px;\n color: var(--mj-text-secondary);\n max-width: 200px;\n}\n\n.mj-flow-editor-legend-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mj-flow-editor-legend-section {\n margin-bottom: 8px;\n}\n\n.mj-flow-editor-legend-section:last-child {\n margin-bottom: 0;\n}\n\n.mj-flow-editor-legend-heading {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n margin-bottom: 4px;\n}\n\n.mj-flow-editor-legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 2px 0;\n font-size: 11px;\n color: var(--mj-text-secondary);\n}\n\n.mj-flow-editor-legend-svg,\n.mj-flow-editor-legend-line-svg {\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-swatch {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n.mj-flow-editor-legend-box {\n display: inline-block;\n width: 14px;\n height: 10px;\n border: 2px solid;\n border-radius: var(--mj-radius-sm);\n flex-shrink: 0;\n}\n\n/* \u2500\u2500 Context Menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-context-menu {\n position: fixed;\n min-width: 180px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-lg);\n padding: 4px;\n z-index: 9999;\n animation: mj-ctx-fade-in 0.1s ease-out;\n}\n\n@keyframes mj-ctx-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n}\n\n.mj-flow-context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n font-size: var(--mj-text-sm);\n font-weight: 450;\n color: var(--mj-text-secondary);\n cursor: pointer;\n border-radius: 5px;\n text-align: left;\n transition: background-color 0.1s ease;\n}\n\n.mj-flow-context-menu-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mj-flow-context-menu-item i {\n width: 16px;\n text-align: center;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-shortcut {\n margin-left: auto;\n padding: 0 4px;\n border: 1px solid var(--mj-border-default);\n border-radius: 3px;\n font-size: 10px;\n font-family: inherit;\n color: var(--mj-text-muted);\n}\n\n.mj-flow-context-menu-item--danger {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-item--danger:hover {\n background-color: var(--mj-status-error-subtle);\n}\n\n.mj-flow-context-menu-item--danger i {\n color: var(--mj-status-error);\n}\n\n.mj-flow-context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 8px;\n}\n\n/* \u2500\u2500 Focus Indicators (Accessibility) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mj-flow-toolbar-btn:focus-visible,\n.mj-agent-editor-btn:focus-visible,\n.mj-agent-editor-view-btn:focus-visible,\n.mj-agent-props-close:focus-visible,\n.mj-agent-props-delete-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.mj-flow-palette-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 1px;\n border-radius: var(--mj-radius-md);\n}\n"] }]
|
|
1052
1159
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.FlowStateService }, { type: i2.FlowLayoutService }], { Nodes: [{
|
|
1053
1160
|
type: Input
|
|
1054
1161
|
}], Connections: [{
|
|
@@ -1067,6 +1174,10 @@ export class FlowEditorComponent {
|
|
|
1067
1174
|
type: Input
|
|
1068
1175
|
}], ShowToolbar: [{
|
|
1069
1176
|
type: Input
|
|
1177
|
+
}], ToolbarVisibility: [{
|
|
1178
|
+
type: Input
|
|
1179
|
+
}], ToolbarAlign: [{
|
|
1180
|
+
type: Input
|
|
1070
1181
|
}], ShowLegend: [{
|
|
1071
1182
|
type: Input
|
|
1072
1183
|
}], GridSize: [{
|
|
@@ -1107,12 +1218,18 @@ export class FlowEditorComponent {
|
|
|
1107
1218
|
type: Output
|
|
1108
1219
|
}], ConnectionEditRequested: [{
|
|
1109
1220
|
type: Output
|
|
1221
|
+
}], BeforeContextMenu: [{
|
|
1222
|
+
type: Output
|
|
1223
|
+
}], AfterContextMenuAction: [{
|
|
1224
|
+
type: Output
|
|
1110
1225
|
}], GridToggled: [{
|
|
1111
1226
|
type: Output
|
|
1112
1227
|
}], MinimapToggled: [{
|
|
1113
1228
|
type: Output
|
|
1114
1229
|
}], LegendToggled: [{
|
|
1115
1230
|
type: Output
|
|
1231
|
+
}], ToolbarVisibilityChanged: [{
|
|
1232
|
+
type: Output
|
|
1116
1233
|
}], fFlow: [{
|
|
1117
1234
|
type: ViewChild,
|
|
1118
1235
|
args: [FFlowComponent]
|
|
@@ -1132,5 +1249,12 @@ export class FlowEditorComponent {
|
|
|
1132
1249
|
type: HostListener,
|
|
1133
1250
|
args: ['keydown', ['$event']]
|
|
1134
1251
|
}] }); })();
|
|
1135
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FlowEditorComponent, { className: "FlowEditorComponent", filePath: "src/lib/components/flow-editor.component.ts", lineNumber:
|
|
1252
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FlowEditorComponent, { className: "FlowEditorComponent", filePath: "src/lib/components/flow-editor.component.ts", lineNumber: 46 }); })();
|
|
1253
|
+
function defaultContextMenuItems(target) {
|
|
1254
|
+
const noun = target === 'node' ? 'Node' : 'Connection';
|
|
1255
|
+
return [
|
|
1256
|
+
{ ID: 'edit', Label: `Edit ${noun}`, Icon: 'fa-pen-to-square' },
|
|
1257
|
+
{ ID: 'remove', Label: `Remove ${noun}`, Icon: 'fa-trash-can', Danger: true },
|
|
1258
|
+
];
|
|
1259
|
+
}
|
|
1136
1260
|
//# sourceMappingURL=flow-editor.component.js.map
|