@utisha/graph-editor 1.0.0-beta.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -75,6 +75,8 @@ class GraphEditorComponent {
|
|
|
75
75
|
height: viewportHeight * 2
|
|
76
76
|
};
|
|
77
77
|
});
|
|
78
|
+
// Shadow configuration (defaults to true)
|
|
79
|
+
shadowsEnabled = computed(() => this.config.theme?.shadows !== false);
|
|
78
80
|
// Selected edge info for direction selector positioning
|
|
79
81
|
selectedEdgeMidpoint = computed(() => {
|
|
80
82
|
const sel = this.selection();
|
|
@@ -730,7 +732,37 @@ class GraphEditorComponent {
|
|
|
730
732
|
}
|
|
731
733
|
onContextMenu(event) {
|
|
732
734
|
event.preventDefault();
|
|
733
|
-
|
|
735
|
+
const svgRect = this.canvasSvgRef()?.nativeElement.getBoundingClientRect();
|
|
736
|
+
if (!svgRect)
|
|
737
|
+
return;
|
|
738
|
+
// Calculate position in graph coordinates
|
|
739
|
+
const x = (event.clientX - svgRect.left - this.panX()) / this.scale();
|
|
740
|
+
const y = (event.clientY - svgRect.top - this.panY()) / this.scale();
|
|
741
|
+
// Check if clicking on a node
|
|
742
|
+
const nodeId = this.findNodeAtPosition({ x, y });
|
|
743
|
+
if (nodeId) {
|
|
744
|
+
this.contextMenu.emit({
|
|
745
|
+
type: 'node',
|
|
746
|
+
position: { x: event.clientX, y: event.clientY },
|
|
747
|
+
nodeId
|
|
748
|
+
});
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
// Check if clicking on an edge (use hit area logic)
|
|
752
|
+
const edgeId = this.findEdgeAtPosition({ x, y });
|
|
753
|
+
if (edgeId) {
|
|
754
|
+
this.contextMenu.emit({
|
|
755
|
+
type: 'edge',
|
|
756
|
+
position: { x: event.clientX, y: event.clientY },
|
|
757
|
+
edgeId
|
|
758
|
+
});
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
// Canvas click
|
|
762
|
+
this.contextMenu.emit({
|
|
763
|
+
type: 'canvas',
|
|
764
|
+
position: { x: event.clientX, y: event.clientY }
|
|
765
|
+
});
|
|
734
766
|
}
|
|
735
767
|
// Helper methods
|
|
736
768
|
emitGraphChange() {
|
|
@@ -833,6 +865,40 @@ class GraphEditorComponent {
|
|
|
833
865
|
const nodeConfig = this.config.nodes.types.find(t => t.type === node.type);
|
|
834
866
|
return nodeConfig?.icon || '●';
|
|
835
867
|
}
|
|
868
|
+
getIconPosition(node) {
|
|
869
|
+
const size = this.getNodeSize(node);
|
|
870
|
+
const pos = this.config.nodes.iconPosition || 'top-left';
|
|
871
|
+
const padding = size.height * 0.25;
|
|
872
|
+
const iconSize = size.height * 0.28;
|
|
873
|
+
const positions = {
|
|
874
|
+
'top-left': { x: padding, y: padding },
|
|
875
|
+
'top': { x: size.width / 2, y: padding },
|
|
876
|
+
'top-right': { x: size.width - padding, y: padding },
|
|
877
|
+
'right': { x: size.width - padding, y: size.height / 2 },
|
|
878
|
+
'bottom-right': { x: size.width - padding, y: size.height - padding },
|
|
879
|
+
'bottom': { x: size.width / 2, y: size.height - padding },
|
|
880
|
+
'bottom-left': { x: padding, y: size.height - padding },
|
|
881
|
+
'left': { x: padding, y: size.height / 2 }
|
|
882
|
+
};
|
|
883
|
+
return positions[pos] || positions['left'];
|
|
884
|
+
}
|
|
885
|
+
getLabelPosition(node) {
|
|
886
|
+
const size = this.getNodeSize(node);
|
|
887
|
+
const pos = this.config.nodes.iconPosition || 'top-left';
|
|
888
|
+
const padding = size.height * 0.25;
|
|
889
|
+
// Label position adjusts based on icon position
|
|
890
|
+
const labelPositions = {
|
|
891
|
+
'top-left': { x: size.width / 2 + padding / 2, y: size.height / 2 + 4 },
|
|
892
|
+
'top': { x: size.width / 2, y: size.height / 2 + padding / 2 },
|
|
893
|
+
'top-right': { x: size.width / 2 - padding / 2, y: size.height / 2 + 4 },
|
|
894
|
+
'right': { x: size.width / 2 - padding / 2, y: size.height / 2 },
|
|
895
|
+
'bottom-right': { x: size.width / 2 - padding / 2, y: size.height / 2 - 4 },
|
|
896
|
+
'bottom': { x: size.width / 2, y: size.height / 2 - padding / 2 },
|
|
897
|
+
'bottom-left': { x: size.width / 2 + padding / 2, y: size.height / 2 - 4 },
|
|
898
|
+
'left': { x: size.width / 2 + padding / 2, y: size.height / 2 }
|
|
899
|
+
};
|
|
900
|
+
return labelPositions[pos] || labelPositions['top-left'];
|
|
901
|
+
}
|
|
836
902
|
findNodeAtPosition(pos) {
|
|
837
903
|
for (const node of this.internalGraph().nodes) {
|
|
838
904
|
const size = this.getNodeSize(node);
|
|
@@ -845,6 +911,34 @@ class GraphEditorComponent {
|
|
|
845
911
|
}
|
|
846
912
|
return null;
|
|
847
913
|
}
|
|
914
|
+
findEdgeAtPosition(pos) {
|
|
915
|
+
const hitDistance = 10; // pixels tolerance
|
|
916
|
+
for (const edge of this.internalGraph().edges) {
|
|
917
|
+
const sourcePoint = this.getEdgeSourcePoint(edge);
|
|
918
|
+
const targetPoint = this.getEdgeTargetPoint(edge);
|
|
919
|
+
// Calculate distance from point to line segment
|
|
920
|
+
const dist = this.pointToSegmentDistance(pos, sourcePoint, targetPoint);
|
|
921
|
+
if (dist < hitDistance) {
|
|
922
|
+
return edge.id;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
return null;
|
|
926
|
+
}
|
|
927
|
+
pointToSegmentDistance(point, lineStart, lineEnd) {
|
|
928
|
+
const dx = lineEnd.x - lineStart.x;
|
|
929
|
+
const dy = lineEnd.y - lineStart.y;
|
|
930
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
931
|
+
if (lengthSquared === 0) {
|
|
932
|
+
// Line segment is a point
|
|
933
|
+
return Math.sqrt((point.x - lineStart.x) ** 2 + (point.y - lineStart.y) ** 2);
|
|
934
|
+
}
|
|
935
|
+
// Project point onto line segment
|
|
936
|
+
let t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / lengthSquared;
|
|
937
|
+
t = Math.max(0, Math.min(1, t));
|
|
938
|
+
const projX = lineStart.x + t * dx;
|
|
939
|
+
const projY = lineStart.y + t * dy;
|
|
940
|
+
return Math.sqrt((point.x - projX) ** 2 + (point.y - projY) ** 2);
|
|
941
|
+
}
|
|
848
942
|
getNodePorts(node) {
|
|
849
943
|
const size = this.getNodeSize(node);
|
|
850
944
|
return [
|
|
@@ -938,10 +1032,10 @@ class GraphEditorComponent {
|
|
|
938
1032
|
>
|
|
939
1033
|
<span class="icon">∕</span>
|
|
940
1034
|
</button>
|
|
941
|
-
|
|
1035
|
+
|
|
942
1036
|
<!-- Divider -->
|
|
943
1037
|
<div class="palette-divider"></div>
|
|
944
|
-
|
|
1038
|
+
|
|
945
1039
|
<!-- Node types -->
|
|
946
1040
|
@for (nodeType of config.nodes.types; track nodeType.type) {
|
|
947
1041
|
<button
|
|
@@ -955,7 +1049,7 @@ class GraphEditorComponent {
|
|
|
955
1049
|
}
|
|
956
1050
|
</div>
|
|
957
1051
|
}
|
|
958
|
-
|
|
1052
|
+
|
|
959
1053
|
<svg
|
|
960
1054
|
#canvasSvg
|
|
961
1055
|
[class.tool-line]="activeTool() === 'line'"
|
|
@@ -1020,24 +1114,38 @@ class GraphEditorComponent {
|
|
|
1020
1114
|
<!-- Layer 0.5: Preview line for line tool (rubber-band) -->
|
|
1021
1115
|
@if (previewLine()) {
|
|
1022
1116
|
<line
|
|
1117
|
+
class="preview-line"
|
|
1023
1118
|
[attr.x1]="previewLine()!.source.x"
|
|
1024
1119
|
[attr.y1]="previewLine()!.source.y"
|
|
1025
1120
|
[attr.x2]="previewLine()!.target.x"
|
|
1026
1121
|
[attr.y2]="previewLine()!.target.y"
|
|
1027
1122
|
stroke="#3b82f6"
|
|
1028
|
-
stroke-width="2"
|
|
1029
|
-
stroke-dasharray="6
|
|
1030
|
-
|
|
1123
|
+
stroke-width="2.5"
|
|
1124
|
+
stroke-dasharray="8,6"
|
|
1125
|
+
stroke-linecap="round"
|
|
1126
|
+
opacity="0.7"
|
|
1031
1127
|
/>
|
|
1032
1128
|
}
|
|
1033
1129
|
|
|
1034
1130
|
<!-- Layer 1: Edge paths (behind everything) -->
|
|
1035
1131
|
@for (edge of internalGraph().edges; track edge.id) {
|
|
1132
|
+
<!-- Edge shadow for depth (optional) -->
|
|
1133
|
+
@if (shadowsEnabled()) {
|
|
1134
|
+
<path
|
|
1135
|
+
class="edge-shadow"
|
|
1136
|
+
[attr.d]="getEdgePath(edge)"
|
|
1137
|
+
stroke="rgba(0,0,0,0.06)"
|
|
1138
|
+
stroke-width="6"
|
|
1139
|
+
fill="none"
|
|
1140
|
+
stroke-linecap="round"
|
|
1141
|
+
[attr.transform]="'translate(1, 2)'"
|
|
1142
|
+
/>
|
|
1143
|
+
}
|
|
1036
1144
|
<!-- Invisible wide hit-area for easier clicking (hand tool only) -->
|
|
1037
1145
|
<path
|
|
1038
1146
|
[attr.d]="getEdgePath(edge)"
|
|
1039
1147
|
stroke="transparent"
|
|
1040
|
-
[attr.stroke-width]="
|
|
1148
|
+
[attr.stroke-width]="20"
|
|
1041
1149
|
fill="none"
|
|
1042
1150
|
class="edge-hit-area"
|
|
1043
1151
|
[attr.pointer-events]="activeTool() === 'hand' ? 'stroke' : 'none'"
|
|
@@ -1046,10 +1154,12 @@ class GraphEditorComponent {
|
|
|
1046
1154
|
/>
|
|
1047
1155
|
<!-- Visible edge line -->
|
|
1048
1156
|
<path
|
|
1157
|
+
class="edge-line"
|
|
1049
1158
|
[attr.d]="getEdgePath(edge)"
|
|
1050
|
-
[attr.stroke]="
|
|
1051
|
-
[attr.stroke-width]="2"
|
|
1159
|
+
[attr.stroke]="selection().edges.includes(edge.id) ? '#3b82f6' : '#94a3b8'"
|
|
1160
|
+
[attr.stroke-width]="selection().edges.includes(edge.id) ? 2.5 : 2"
|
|
1052
1161
|
fill="none"
|
|
1162
|
+
stroke-linecap="round"
|
|
1053
1163
|
[class.selected]="selection().edges.includes(edge.id)"
|
|
1054
1164
|
[attr.marker-end]="getEdgeMarkerEnd(edge)"
|
|
1055
1165
|
[attr.marker-start]="getEdgeMarkerStart(edge)"
|
|
@@ -1068,45 +1178,51 @@ class GraphEditorComponent {
|
|
|
1068
1178
|
(click)="onNodeClick($event, node)"
|
|
1069
1179
|
(dblclick)="nodeDoubleClick.emit(node)"
|
|
1070
1180
|
>
|
|
1181
|
+
<!-- Node shadow (optional) -->
|
|
1182
|
+
@if (shadowsEnabled()) {
|
|
1183
|
+
<rect
|
|
1184
|
+
class="node-shadow"
|
|
1185
|
+
[attr.width]="getNodeSize(node).width"
|
|
1186
|
+
[attr.height]="getNodeSize(node).height"
|
|
1187
|
+
fill="rgba(0,0,0,0.08)"
|
|
1188
|
+
rx="12"
|
|
1189
|
+
transform="translate(2, 3)"
|
|
1190
|
+
style="filter: blur(4px);"
|
|
1191
|
+
/>
|
|
1192
|
+
}
|
|
1071
1193
|
<!-- Node background -->
|
|
1072
1194
|
<rect
|
|
1195
|
+
class="node-bg"
|
|
1073
1196
|
[attr.width]="getNodeSize(node).width"
|
|
1074
1197
|
[attr.height]="getNodeSize(node).height"
|
|
1075
|
-
|
|
1076
|
-
[attr.stroke]="selection().nodes.includes(node.id) ? '#3b82f6' : '#
|
|
1077
|
-
[attr.stroke-width]="selection().nodes.includes(node.id) ?
|
|
1078
|
-
rx="
|
|
1198
|
+
fill="white"
|
|
1199
|
+
[attr.stroke]="selection().nodes.includes(node.id) ? '#3b82f6' : '#e2e8f0'"
|
|
1200
|
+
[attr.stroke-width]="selection().nodes.includes(node.id) ? 2.5 : 1.5"
|
|
1201
|
+
rx="12"
|
|
1079
1202
|
/>
|
|
1080
|
-
|
|
1081
|
-
<!-- Node type icon
|
|
1082
|
-
<
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
y="28"
|
|
1094
|
-
text-anchor="middle"
|
|
1095
|
-
dominant-baseline="middle"
|
|
1096
|
-
font-size="20"
|
|
1097
|
-
fill="#374151"
|
|
1098
|
-
>
|
|
1099
|
-
{{ getNodeTypeIcon(node) }}
|
|
1100
|
-
</text>
|
|
1101
|
-
</g>
|
|
1102
|
-
|
|
1203
|
+
|
|
1204
|
+
<!-- Node type icon -->
|
|
1205
|
+
<text
|
|
1206
|
+
class="node-icon"
|
|
1207
|
+
[attr.x]="getIconPosition(node).x"
|
|
1208
|
+
[attr.y]="getIconPosition(node).y"
|
|
1209
|
+
text-anchor="middle"
|
|
1210
|
+
dominant-baseline="middle"
|
|
1211
|
+
[attr.font-size]="getNodeSize(node).height * 0.28"
|
|
1212
|
+
>
|
|
1213
|
+
{{ getNodeTypeIcon(node) }}
|
|
1214
|
+
</text>
|
|
1215
|
+
|
|
1103
1216
|
<!-- Node label -->
|
|
1104
1217
|
<text
|
|
1105
|
-
|
|
1106
|
-
[attr.
|
|
1218
|
+
class="node-label"
|
|
1219
|
+
[attr.x]="getLabelPosition(node).x"
|
|
1220
|
+
[attr.y]="getLabelPosition(node).y"
|
|
1107
1221
|
text-anchor="middle"
|
|
1108
1222
|
dominant-baseline="middle"
|
|
1109
1223
|
font-size="14"
|
|
1224
|
+
font-weight="500"
|
|
1225
|
+
fill="#1e293b"
|
|
1110
1226
|
>
|
|
1111
1227
|
{{ node.data['name'] || node.type }}
|
|
1112
1228
|
</text>
|
|
@@ -1150,7 +1266,7 @@ class GraphEditorComponent {
|
|
|
1150
1266
|
class="edge-endpoint selected"
|
|
1151
1267
|
(mousedown)="onEdgeEndpointMouseDown($event, edge, 'source')"
|
|
1152
1268
|
/>
|
|
1153
|
-
|
|
1269
|
+
|
|
1154
1270
|
<!-- Target endpoint -->
|
|
1155
1271
|
<circle
|
|
1156
1272
|
[attr.cx]="getEdgeTargetPoint(edge).x"
|
|
@@ -1208,7 +1324,7 @@ class GraphEditorComponent {
|
|
|
1208
1324
|
</div>
|
|
1209
1325
|
}
|
|
1210
1326
|
</div>
|
|
1211
|
-
`, isInline: true, styles: [".graph-editor-container{display:flex;width:100%;height:100%;position:relative;background:var(--graph-editor-canvas-bg, #f8f9fa)}.graph-palette-overlay{position:absolute;top:16px;left:16px;display:flex;gap:4px;z-index:10;background:#fffffff2;padding:6px;border-radius:var(--radius-md, 8px);box-shadow:0 2px 8px #0000001a;backdrop-filter:blur(4px)}.palette-item{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:1.5px solid var(--neutral-200, #e5e7eb);border-radius:var(--radius-md, 8px);background:var(--white, #fff);color:var(--neutral-600, #4b5563);cursor:pointer;-webkit-user-select:none;user-select:none;transition:all .15s ease;font-size:20px}.palette-item:focus-visible{outline:2px solid var(--indigo-400, #818cf8);outline-offset:2px}.palette-item:hover{background:var(--neutral-50, #f9fafb);border-color:var(--interactive, #3b82f6);color:var(--interactive, #3b82f6);transform:translateY(-1px);box-shadow:0 2px 6px #00000014}.palette-item:active{transform:translateY(0);box-shadow:none}.palette-item.tool-item.active{background:var(--interactive, #3b82f6);border-color:var(--interactive, #3b82f6);color:#fff}.palette-item.tool-item.active:hover{background:var(--interactive-hover, #2563eb);border-color:var(--interactive-hover, #2563eb);color:#fff}.palette-divider{width:1px;background:var(--neutral-200, #e5e7eb);align-self:stretch;margin:4px 2px}.graph-canvas-wrapper{flex:1;position:relative;overflow:hidden}.graph-canvas{width:100%;height:100%;cursor:grab}.graph-canvas:active{cursor:grabbing}.graph-canvas.tool-line,.graph-canvas.tool-line .graph-node{cursor:crosshair}.graph-node{cursor:move;user-select:none;-webkit-user-select:none}.graph-node text{pointer-events:none}.graph-node.selected
|
|
1327
|
+
`, isInline: true, styles: [".graph-editor-container{display:flex;width:100%;height:100%;position:relative;background:var(--graph-editor-canvas-bg, #f8f9fa)}.graph-palette-overlay{position:absolute;top:16px;left:16px;display:flex;gap:4px;z-index:10;background:#fffffff2;padding:6px;border-radius:var(--radius-md, 8px);box-shadow:0 2px 8px #0000001a;backdrop-filter:blur(4px)}.palette-item{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:1.5px solid var(--neutral-200, #e5e7eb);border-radius:var(--radius-md, 8px);background:var(--white, #fff);color:var(--neutral-600, #4b5563);cursor:pointer;-webkit-user-select:none;user-select:none;transition:all .15s ease;font-size:20px}.palette-item:focus-visible{outline:2px solid var(--indigo-400, #818cf8);outline-offset:2px}.palette-item:hover{background:var(--neutral-50, #f9fafb);border-color:var(--interactive, #3b82f6);color:var(--interactive, #3b82f6);transform:translateY(-1px);box-shadow:0 2px 6px #00000014}.palette-item:active{transform:translateY(0);box-shadow:none}.palette-item.tool-item.active{background:var(--interactive, #3b82f6);border-color:var(--interactive, #3b82f6);color:#fff}.palette-item.tool-item.active:hover{background:var(--interactive-hover, #2563eb);border-color:var(--interactive-hover, #2563eb);color:#fff}.palette-divider{width:1px;background:var(--neutral-200, #e5e7eb);align-self:stretch;margin:4px 2px}.graph-canvas-wrapper{flex:1;position:relative;overflow:hidden}.graph-canvas{width:100%;height:100%;cursor:grab}.graph-canvas:active{cursor:grabbing}.graph-canvas.tool-line,.graph-canvas.tool-line .graph-node{cursor:crosshair}.graph-node{cursor:move;user-select:none;-webkit-user-select:none;transition:transform .1s ease-out}.graph-node:hover .node-bg{stroke:#cbd5e1}.graph-node text{pointer-events:none}.graph-node .node-label{font-family:system-ui,-apple-system,sans-serif}.graph-node.selected .node-bg{stroke:#3b82f6;filter:drop-shadow(0 4px 12px rgba(59,130,246,.25))}.edge-line{transition:stroke .15s,stroke-width .15s}.edge-line.selected{filter:drop-shadow(0 2px 4px rgba(59,130,246,.3))}.edge-hit-area{cursor:pointer}.edge-endpoint{cursor:pointer;transition:r .2s,fill .2s}.edge-endpoint:hover{r:8;fill:#2563eb}.edge-endpoint.selected{fill:#2563eb}.attachment-point{cursor:crosshair;transition:all .2s}.attachment-point.hovered{filter:drop-shadow(0 0 4px rgba(37,99,235,.6))}.validation-panel{position:absolute;bottom:0;left:0;right:0;max-height:200px;overflow-y:auto;background:#fff;border-top:1px solid #e5e7eb;padding:16px}.error-item{padding:8px 12px;margin-bottom:8px;background:#fee2e2;border-left:3px solid #ef4444;border-radius:4px;font-size:14px}.error-item.warning{background:#fef3c7;border-left-color:#f59e0b}.edge-direction-selector{position:absolute;transform:translate(-50%,-100%);margin-top:-12px;display:flex;gap:2px;background:#fffffff2;padding:4px;border-radius:6px;box-shadow:0 2px 8px #00000026;backdrop-filter:blur(4px);z-index:20;pointer-events:auto}.direction-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid #e5e7eb;border-radius:4px;background:#fff;cursor:pointer;font-size:16px;transition:all .15s;color:#6b7280}.direction-btn:hover{background:#f3f4f6;border-color:#3b82f6;color:#3b82f6}.direction-btn.active{background:#3b82f6;border-color:#3b82f6;color:#fff}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1212
1328
|
}
|
|
1213
1329
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: GraphEditorComponent, decorators: [{
|
|
1214
1330
|
type: Component,
|
|
@@ -1240,10 +1356,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1240
1356
|
>
|
|
1241
1357
|
<span class="icon">∕</span>
|
|
1242
1358
|
</button>
|
|
1243
|
-
|
|
1359
|
+
|
|
1244
1360
|
<!-- Divider -->
|
|
1245
1361
|
<div class="palette-divider"></div>
|
|
1246
|
-
|
|
1362
|
+
|
|
1247
1363
|
<!-- Node types -->
|
|
1248
1364
|
@for (nodeType of config.nodes.types; track nodeType.type) {
|
|
1249
1365
|
<button
|
|
@@ -1257,7 +1373,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1257
1373
|
}
|
|
1258
1374
|
</div>
|
|
1259
1375
|
}
|
|
1260
|
-
|
|
1376
|
+
|
|
1261
1377
|
<svg
|
|
1262
1378
|
#canvasSvg
|
|
1263
1379
|
[class.tool-line]="activeTool() === 'line'"
|
|
@@ -1322,24 +1438,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1322
1438
|
<!-- Layer 0.5: Preview line for line tool (rubber-band) -->
|
|
1323
1439
|
@if (previewLine()) {
|
|
1324
1440
|
<line
|
|
1441
|
+
class="preview-line"
|
|
1325
1442
|
[attr.x1]="previewLine()!.source.x"
|
|
1326
1443
|
[attr.y1]="previewLine()!.source.y"
|
|
1327
1444
|
[attr.x2]="previewLine()!.target.x"
|
|
1328
1445
|
[attr.y2]="previewLine()!.target.y"
|
|
1329
1446
|
stroke="#3b82f6"
|
|
1330
|
-
stroke-width="2"
|
|
1331
|
-
stroke-dasharray="6
|
|
1332
|
-
|
|
1447
|
+
stroke-width="2.5"
|
|
1448
|
+
stroke-dasharray="8,6"
|
|
1449
|
+
stroke-linecap="round"
|
|
1450
|
+
opacity="0.7"
|
|
1333
1451
|
/>
|
|
1334
1452
|
}
|
|
1335
1453
|
|
|
1336
1454
|
<!-- Layer 1: Edge paths (behind everything) -->
|
|
1337
1455
|
@for (edge of internalGraph().edges; track edge.id) {
|
|
1456
|
+
<!-- Edge shadow for depth (optional) -->
|
|
1457
|
+
@if (shadowsEnabled()) {
|
|
1458
|
+
<path
|
|
1459
|
+
class="edge-shadow"
|
|
1460
|
+
[attr.d]="getEdgePath(edge)"
|
|
1461
|
+
stroke="rgba(0,0,0,0.06)"
|
|
1462
|
+
stroke-width="6"
|
|
1463
|
+
fill="none"
|
|
1464
|
+
stroke-linecap="round"
|
|
1465
|
+
[attr.transform]="'translate(1, 2)'"
|
|
1466
|
+
/>
|
|
1467
|
+
}
|
|
1338
1468
|
<!-- Invisible wide hit-area for easier clicking (hand tool only) -->
|
|
1339
1469
|
<path
|
|
1340
1470
|
[attr.d]="getEdgePath(edge)"
|
|
1341
1471
|
stroke="transparent"
|
|
1342
|
-
[attr.stroke-width]="
|
|
1472
|
+
[attr.stroke-width]="20"
|
|
1343
1473
|
fill="none"
|
|
1344
1474
|
class="edge-hit-area"
|
|
1345
1475
|
[attr.pointer-events]="activeTool() === 'hand' ? 'stroke' : 'none'"
|
|
@@ -1348,10 +1478,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1348
1478
|
/>
|
|
1349
1479
|
<!-- Visible edge line -->
|
|
1350
1480
|
<path
|
|
1481
|
+
class="edge-line"
|
|
1351
1482
|
[attr.d]="getEdgePath(edge)"
|
|
1352
|
-
[attr.stroke]="
|
|
1353
|
-
[attr.stroke-width]="2"
|
|
1483
|
+
[attr.stroke]="selection().edges.includes(edge.id) ? '#3b82f6' : '#94a3b8'"
|
|
1484
|
+
[attr.stroke-width]="selection().edges.includes(edge.id) ? 2.5 : 2"
|
|
1354
1485
|
fill="none"
|
|
1486
|
+
stroke-linecap="round"
|
|
1355
1487
|
[class.selected]="selection().edges.includes(edge.id)"
|
|
1356
1488
|
[attr.marker-end]="getEdgeMarkerEnd(edge)"
|
|
1357
1489
|
[attr.marker-start]="getEdgeMarkerStart(edge)"
|
|
@@ -1370,45 +1502,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1370
1502
|
(click)="onNodeClick($event, node)"
|
|
1371
1503
|
(dblclick)="nodeDoubleClick.emit(node)"
|
|
1372
1504
|
>
|
|
1505
|
+
<!-- Node shadow (optional) -->
|
|
1506
|
+
@if (shadowsEnabled()) {
|
|
1507
|
+
<rect
|
|
1508
|
+
class="node-shadow"
|
|
1509
|
+
[attr.width]="getNodeSize(node).width"
|
|
1510
|
+
[attr.height]="getNodeSize(node).height"
|
|
1511
|
+
fill="rgba(0,0,0,0.08)"
|
|
1512
|
+
rx="12"
|
|
1513
|
+
transform="translate(2, 3)"
|
|
1514
|
+
style="filter: blur(4px);"
|
|
1515
|
+
/>
|
|
1516
|
+
}
|
|
1373
1517
|
<!-- Node background -->
|
|
1374
1518
|
<rect
|
|
1519
|
+
class="node-bg"
|
|
1375
1520
|
[attr.width]="getNodeSize(node).width"
|
|
1376
1521
|
[attr.height]="getNodeSize(node).height"
|
|
1377
|
-
|
|
1378
|
-
[attr.stroke]="selection().nodes.includes(node.id) ? '#3b82f6' : '#
|
|
1379
|
-
[attr.stroke-width]="selection().nodes.includes(node.id) ?
|
|
1380
|
-
rx="
|
|
1522
|
+
fill="white"
|
|
1523
|
+
[attr.stroke]="selection().nodes.includes(node.id) ? '#3b82f6' : '#e2e8f0'"
|
|
1524
|
+
[attr.stroke-width]="selection().nodes.includes(node.id) ? 2.5 : 1.5"
|
|
1525
|
+
rx="12"
|
|
1381
1526
|
/>
|
|
1382
|
-
|
|
1383
|
-
<!-- Node type icon
|
|
1384
|
-
<
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
y="28"
|
|
1396
|
-
text-anchor="middle"
|
|
1397
|
-
dominant-baseline="middle"
|
|
1398
|
-
font-size="20"
|
|
1399
|
-
fill="#374151"
|
|
1400
|
-
>
|
|
1401
|
-
{{ getNodeTypeIcon(node) }}
|
|
1402
|
-
</text>
|
|
1403
|
-
</g>
|
|
1404
|
-
|
|
1527
|
+
|
|
1528
|
+
<!-- Node type icon -->
|
|
1529
|
+
<text
|
|
1530
|
+
class="node-icon"
|
|
1531
|
+
[attr.x]="getIconPosition(node).x"
|
|
1532
|
+
[attr.y]="getIconPosition(node).y"
|
|
1533
|
+
text-anchor="middle"
|
|
1534
|
+
dominant-baseline="middle"
|
|
1535
|
+
[attr.font-size]="getNodeSize(node).height * 0.28"
|
|
1536
|
+
>
|
|
1537
|
+
{{ getNodeTypeIcon(node) }}
|
|
1538
|
+
</text>
|
|
1539
|
+
|
|
1405
1540
|
<!-- Node label -->
|
|
1406
1541
|
<text
|
|
1407
|
-
|
|
1408
|
-
[attr.
|
|
1542
|
+
class="node-label"
|
|
1543
|
+
[attr.x]="getLabelPosition(node).x"
|
|
1544
|
+
[attr.y]="getLabelPosition(node).y"
|
|
1409
1545
|
text-anchor="middle"
|
|
1410
1546
|
dominant-baseline="middle"
|
|
1411
1547
|
font-size="14"
|
|
1548
|
+
font-weight="500"
|
|
1549
|
+
fill="#1e293b"
|
|
1412
1550
|
>
|
|
1413
1551
|
{{ node.data['name'] || node.type }}
|
|
1414
1552
|
</text>
|
|
@@ -1452,7 +1590,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1452
1590
|
class="edge-endpoint selected"
|
|
1453
1591
|
(mousedown)="onEdgeEndpointMouseDown($event, edge, 'source')"
|
|
1454
1592
|
/>
|
|
1455
|
-
|
|
1593
|
+
|
|
1456
1594
|
<!-- Target endpoint -->
|
|
1457
1595
|
<circle
|
|
1458
1596
|
[attr.cx]="getEdgeTargetPoint(edge).x"
|
|
@@ -1510,7 +1648,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
|
|
|
1510
1648
|
</div>
|
|
1511
1649
|
}
|
|
1512
1650
|
</div>
|
|
1513
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".graph-editor-container{display:flex;width:100%;height:100%;position:relative;background:var(--graph-editor-canvas-bg, #f8f9fa)}.graph-palette-overlay{position:absolute;top:16px;left:16px;display:flex;gap:4px;z-index:10;background:#fffffff2;padding:6px;border-radius:var(--radius-md, 8px);box-shadow:0 2px 8px #0000001a;backdrop-filter:blur(4px)}.palette-item{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:1.5px solid var(--neutral-200, #e5e7eb);border-radius:var(--radius-md, 8px);background:var(--white, #fff);color:var(--neutral-600, #4b5563);cursor:pointer;-webkit-user-select:none;user-select:none;transition:all .15s ease;font-size:20px}.palette-item:focus-visible{outline:2px solid var(--indigo-400, #818cf8);outline-offset:2px}.palette-item:hover{background:var(--neutral-50, #f9fafb);border-color:var(--interactive, #3b82f6);color:var(--interactive, #3b82f6);transform:translateY(-1px);box-shadow:0 2px 6px #00000014}.palette-item:active{transform:translateY(0);box-shadow:none}.palette-item.tool-item.active{background:var(--interactive, #3b82f6);border-color:var(--interactive, #3b82f6);color:#fff}.palette-item.tool-item.active:hover{background:var(--interactive-hover, #2563eb);border-color:var(--interactive-hover, #2563eb);color:#fff}.palette-divider{width:1px;background:var(--neutral-200, #e5e7eb);align-self:stretch;margin:4px 2px}.graph-canvas-wrapper{flex:1;position:relative;overflow:hidden}.graph-canvas{width:100%;height:100%;cursor:grab}.graph-canvas:active{cursor:grabbing}.graph-canvas.tool-line,.graph-canvas.tool-line .graph-node{cursor:crosshair}.graph-node{cursor:move;user-select:none;-webkit-user-select:none}.graph-node text{pointer-events:none}.graph-node.selected
|
|
1651
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".graph-editor-container{display:flex;width:100%;height:100%;position:relative;background:var(--graph-editor-canvas-bg, #f8f9fa)}.graph-palette-overlay{position:absolute;top:16px;left:16px;display:flex;gap:4px;z-index:10;background:#fffffff2;padding:6px;border-radius:var(--radius-md, 8px);box-shadow:0 2px 8px #0000001a;backdrop-filter:blur(4px)}.palette-item{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border:1.5px solid var(--neutral-200, #e5e7eb);border-radius:var(--radius-md, 8px);background:var(--white, #fff);color:var(--neutral-600, #4b5563);cursor:pointer;-webkit-user-select:none;user-select:none;transition:all .15s ease;font-size:20px}.palette-item:focus-visible{outline:2px solid var(--indigo-400, #818cf8);outline-offset:2px}.palette-item:hover{background:var(--neutral-50, #f9fafb);border-color:var(--interactive, #3b82f6);color:var(--interactive, #3b82f6);transform:translateY(-1px);box-shadow:0 2px 6px #00000014}.palette-item:active{transform:translateY(0);box-shadow:none}.palette-item.tool-item.active{background:var(--interactive, #3b82f6);border-color:var(--interactive, #3b82f6);color:#fff}.palette-item.tool-item.active:hover{background:var(--interactive-hover, #2563eb);border-color:var(--interactive-hover, #2563eb);color:#fff}.palette-divider{width:1px;background:var(--neutral-200, #e5e7eb);align-self:stretch;margin:4px 2px}.graph-canvas-wrapper{flex:1;position:relative;overflow:hidden}.graph-canvas{width:100%;height:100%;cursor:grab}.graph-canvas:active{cursor:grabbing}.graph-canvas.tool-line,.graph-canvas.tool-line .graph-node{cursor:crosshair}.graph-node{cursor:move;user-select:none;-webkit-user-select:none;transition:transform .1s ease-out}.graph-node:hover .node-bg{stroke:#cbd5e1}.graph-node text{pointer-events:none}.graph-node .node-label{font-family:system-ui,-apple-system,sans-serif}.graph-node.selected .node-bg{stroke:#3b82f6;filter:drop-shadow(0 4px 12px rgba(59,130,246,.25))}.edge-line{transition:stroke .15s,stroke-width .15s}.edge-line.selected{filter:drop-shadow(0 2px 4px rgba(59,130,246,.3))}.edge-hit-area{cursor:pointer}.edge-endpoint{cursor:pointer;transition:r .2s,fill .2s}.edge-endpoint:hover{r:8;fill:#2563eb}.edge-endpoint.selected{fill:#2563eb}.attachment-point{cursor:crosshair;transition:all .2s}.attachment-point.hovered{filter:drop-shadow(0 0 4px rgba(37,99,235,.6))}.validation-panel{position:absolute;bottom:0;left:0;right:0;max-height:200px;overflow-y:auto;background:#fff;border-top:1px solid #e5e7eb;padding:16px}.error-item{padding:8px 12px;margin-bottom:8px;background:#fee2e2;border-left:3px solid #ef4444;border-radius:4px;font-size:14px}.error-item.warning{background:#fef3c7;border-left-color:#f59e0b}.edge-direction-selector{position:absolute;transform:translate(-50%,-100%);margin-top:-12px;display:flex;gap:2px;background:#fffffff2;padding:4px;border-radius:6px;box-shadow:0 2px 8px #00000026;backdrop-filter:blur(4px);z-index:20;pointer-events:auto}.direction-btn{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid #e5e7eb;border-radius:4px;background:#fff;cursor:pointer;font-size:16px;transition:all .15s;color:#6b7280}.direction-btn:hover{background:#f3f4f6;border-color:#3b82f6;color:#3b82f6}.direction-btn.active{background:#3b82f6;border-color:#3b82f6;color:#fff}\n"] }]
|
|
1514
1652
|
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
1515
1653
|
type: Input,
|
|
1516
1654
|
args: [{ required: true }]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utisha-graph-editor.mjs","sources":["../../../projects/graph-editor/src/lib/graph-editor.component.ts","../../../projects/graph-editor/src/public-api.ts","../../../projects/graph-editor/src/utisha-graph-editor.ts"],"sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ElementRef,\n signal,\n computed,\n viewChild,\n ChangeDetectionStrategy,\n OnInit,\n OnChanges,\n SimpleChanges,\n effect\n} from '@angular/core';\n// dagre is loaded dynamically in applyLayout() to avoid compile-time resolution issues\nimport { Graph, GraphNode, GraphEdge, Position } from './graph.model';\nimport {\n GraphEditorConfig,\n SelectionState,\n ValidationResult,\n ContextMenuEvent\n} from './graph-editor.config';\n\n/**\n * Main graph editor component.\n * \n * @example\n * <graph-editor\n * [config]=\"editorConfig\"\n * [graph]=\"currentGraph()\"\n * (graphChange)=\"onGraphChange($event)\"\n * />\n */\n@Component({\n selector: 'graph-editor',\n standalone: true,\n imports: [],\n host: {\n 'tabindex': '0',\n 'style': 'outline: none;',\n '(keydown)': 'onKeyDown($event)'\n },\n template: `\n <div class=\"graph-editor-container\">\n <!-- Canvas with overlaid palette -->\n <div class=\"graph-canvas-wrapper\">\n <!-- Top-left horizontal palette overlay -->\n @if (config.palette?.enabled !== false) {\n <div class=\"graph-palette-overlay\">\n <!-- Tools -->\n <button\n class=\"palette-item tool-item\"\n [class.active]=\"activeTool() === 'hand'\"\n title=\"Hand tool (move nodes)\"\n (click)=\"switchTool('hand')\"\n >\n <span class=\"icon\">✋</span>\n </button>\n <button\n class=\"palette-item tool-item\"\n [class.active]=\"activeTool() === 'line'\"\n title=\"Line tool (draw connections)\"\n (click)=\"switchTool('line')\"\n >\n <span class=\"icon\">∕</span>\n </button>\n \n <!-- Divider -->\n <div class=\"palette-divider\"></div>\n \n <!-- Node types -->\n @for (nodeType of config.nodes.types; track nodeType.type) {\n <button\n class=\"palette-item\"\n [attr.data-node-type]=\"nodeType.type\"\n [attr.title]=\"nodeType.label || nodeType.type\"\n (click)=\"addNode(nodeType.type)\"\n >\n <span class=\"icon\">{{ nodeType.icon || '●' }}</span>\n </button>\n }\n </div>\n }\n \n <svg\n #canvasSvg\n [class.tool-line]=\"activeTool() === 'line'\"\n [attr.width]=\"'100%'\"\n [attr.height]=\"'100%'\"\n (mousedown)=\"onCanvasMouseDown($event)\"\n (mousemove)=\"onCanvasMouseMove($event)\"\n (mouseup)=\"onCanvasMouseUp($event)\"\n (wheel)=\"onWheel($event)\"\n (contextmenu)=\"onContextMenu($event)\"\n >\n <!-- Arrow marker definitions -->\n <defs>\n <marker id=\"arrow-end\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 0 1 L 8 5 L 0 9 z\" fill=\"#94a3b8\"/>\n </marker>\n <marker id=\"arrow-end-selected\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 0 1 L 8 5 L 0 9 z\" fill=\"#3b82f6\"/>\n </marker>\n <marker id=\"arrow-start\" viewBox=\"0 0 10 10\" refX=\"1\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 10 1 L 2 5 L 10 9 z\" fill=\"#94a3b8\"/>\n </marker>\n <marker id=\"arrow-start-selected\" viewBox=\"0 0 10 10\" refX=\"1\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 10 1 L 2 5 L 10 9 z\" fill=\"#3b82f6\"/>\n </marker>\n </defs>\n\n <!-- Main transform group (pan + zoom) -->\n <g [attr.transform]=\"transform()\">\n <!-- Grid (if enabled) -->\n <!-- Grid (if enabled) - extended to cover viewport during pan -->\n @if (config.canvas?.grid?.enabled) {\n <defs>\n <pattern\n id=\"grid\"\n [attr.width]=\"config.canvas!.grid!.size\"\n [attr.height]=\"config.canvas!.grid!.size\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n [attr.d]=\"'M ' + config.canvas!.grid!.size + ' 0 L 0 0 0 ' + config.canvas!.grid!.size\"\n fill=\"none\"\n [attr.stroke]=\"config.canvas!.grid!.color || '#e0e0e0'\"\n stroke-width=\"1\"\n />\n </pattern>\n </defs>\n <!-- Extended grid background covering viewport + pan offset -->\n <rect\n [attr.x]=\"gridBounds().x\"\n [attr.y]=\"gridBounds().y\"\n [attr.width]=\"gridBounds().width\"\n [attr.height]=\"gridBounds().height\"\n fill=\"url(#grid)\"\n />\n }\n\n <!-- Layer 0.5: Preview line for line tool (rubber-band) -->\n @if (previewLine()) {\n <line\n [attr.x1]=\"previewLine()!.source.x\"\n [attr.y1]=\"previewLine()!.source.y\"\n [attr.x2]=\"previewLine()!.target.x\"\n [attr.y2]=\"previewLine()!.target.y\"\n stroke=\"#3b82f6\"\n stroke-width=\"2\"\n stroke-dasharray=\"6,4\"\n opacity=\"0.6\"\n />\n }\n\n <!-- Layer 1: Edge paths (behind everything) -->\n @for (edge of internalGraph().edges; track edge.id) {\n <!-- Invisible wide hit-area for easier clicking (hand tool only) -->\n <path\n [attr.d]=\"getEdgePath(edge)\"\n stroke=\"transparent\"\n [attr.stroke-width]=\"16\"\n fill=\"none\"\n class=\"edge-hit-area\"\n [attr.pointer-events]=\"activeTool() === 'hand' ? 'stroke' : 'none'\"\n (click)=\"onEdgeClick($event, edge)\"\n (dblclick)=\"onEdgeDoubleClick($event, edge)\"\n />\n <!-- Visible edge line -->\n <path\n [attr.d]=\"getEdgePath(edge)\"\n [attr.stroke]=\"getEdgeColor(edge)\"\n [attr.stroke-width]=\"2\"\n fill=\"none\"\n [class.selected]=\"selection().edges.includes(edge.id)\"\n [attr.marker-end]=\"getEdgeMarkerEnd(edge)\"\n [attr.marker-start]=\"getEdgeMarkerStart(edge)\"\n pointer-events=\"none\"\n />\n }\n\n <!-- Layer 2: Nodes -->\n @for (node of internalGraph().nodes; track node.id) {\n <g\n [attr.transform]=\"'translate(' + node.position.x + ',' + node.position.y + ')'\"\n class=\"graph-node\"\n [class.selected]=\"selection().nodes.includes(node.id)\"\n [attr.data-node-id]=\"node.id\"\n (mousedown)=\"onNodeMouseDown($event, node)\"\n (click)=\"onNodeClick($event, node)\"\n (dblclick)=\"nodeDoubleClick.emit(node)\"\n >\n <!-- Node background -->\n <rect\n [attr.width]=\"getNodeSize(node).width\"\n [attr.height]=\"getNodeSize(node).height\"\n [attr.fill]=\"'white'\"\n [attr.stroke]=\"selection().nodes.includes(node.id) ? '#3b82f6' : '#cbd5e0'\"\n [attr.stroke-width]=\"selection().nodes.includes(node.id) ? 3 : 2\"\n rx=\"8\"\n />\n \n <!-- Node type icon badge (top-left, with padding from corner) -->\n <g class=\"node-type-badge\">\n <circle\n cx=\"28\"\n cy=\"28\"\n r=\"16\"\n fill=\"#f3f4f6\"\n stroke=\"#cbd5e0\"\n stroke-width=\"2\"\n />\n <text\n x=\"28\"\n y=\"28\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-size=\"20\"\n fill=\"#374151\"\n >\n {{ getNodeTypeIcon(node) }}\n </text>\n </g>\n \n <!-- Node label -->\n <text\n [attr.x]=\"getNodeSize(node).width / 2\"\n [attr.y]=\"getNodeSize(node).height / 2\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-size=\"14\"\n >\n {{ node.data['name'] || node.type }}\n </text>\n </g>\n }\n\n <!-- Layer 3: Attachment points (on top of nodes) -->\n @for (node of internalGraph().nodes; track node.id) {\n @if (showAttachmentPoints() === node.id) {\n <g [attr.transform]=\"'translate(' + node.position.x + ',' + node.position.y + ')'\">\n @for (port of getNodePorts(node); track port.position) {\n <circle\n [attr.cx]=\"port.x\"\n [attr.cy]=\"port.y\"\n [attr.r]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position ? 8 : 6\"\n [attr.fill]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position ? '#2563eb' : '#94a3b8'\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"attachment-point\"\n [class.hovered]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"onAttachmentPointClick($event, node, port.position)\"\n />\n }\n </g>\n }\n }\n\n <!-- Layer 4: Edge endpoints (only visible when edge is selected) -->\n @for (edge of internalGraph().edges; track edge.id) {\n @if (selection().edges.includes(edge.id)) {\n <g>\n <!-- Source endpoint -->\n <circle\n [attr.cx]=\"getEdgeSourcePoint(edge).x\"\n [attr.cy]=\"getEdgeSourcePoint(edge).y\"\n r=\"6\"\n fill=\"#3b82f6\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"edge-endpoint selected\"\n (mousedown)=\"onEdgeEndpointMouseDown($event, edge, 'source')\"\n />\n \n <!-- Target endpoint -->\n <circle\n [attr.cx]=\"getEdgeTargetPoint(edge).x\"\n [attr.cy]=\"getEdgeTargetPoint(edge).y\"\n r=\"6\"\n fill=\"#3b82f6\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"edge-endpoint selected\"\n (mousedown)=\"onEdgeEndpointMouseDown($event, edge, 'target')\"\n />\n </g>\n }\n }\n </g>\n </svg>\n </div>\n\n <!-- Edge direction selector overlay -->\n @if (selectedEdgeMidpoint()) {\n <div\n class=\"edge-direction-selector\"\n [style.left.px]=\"selectedEdgeMidpoint()!.x\"\n [style.top.px]=\"selectedEdgeMidpoint()!.y\"\n >\n <button\n class=\"direction-btn\"\n [class.active]=\"selectedEdgeMidpoint()!.edge.direction === 'backward'\"\n title=\"Backward\"\n (click)=\"setEdgeDirection('backward')\"\n >←</button>\n <button\n class=\"direction-btn\"\n [class.active]=\"selectedEdgeMidpoint()!.edge.direction === 'bidirectional'\"\n title=\"Bidirectional\"\n (click)=\"setEdgeDirection('bidirectional')\"\n >↔</button>\n <button\n class=\"direction-btn\"\n [class.active]=\"!selectedEdgeMidpoint()!.edge.direction || selectedEdgeMidpoint()!.edge.direction === 'forward'\"\n title=\"Forward\"\n (click)=\"setEdgeDirection('forward')\"\n >→</button>\n </div>\n }\n <!-- Validation errors -->\n @if (validationResult() && !validationResult()!.valid) {\n <div class=\"validation-panel\">\n <h4>Validation Errors</h4>\n @for (error of validationResult()!.errors; track error.rule) {\n <div class=\"error-item\" [class.warning]=\"error.severity === 'warning'\">\n {{ error.message }}\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .graph-editor-container {\n display: flex;\n width: 100%;\n height: 100%;\n position: relative;\n background: var(--graph-editor-canvas-bg, #f8f9fa);\n }\n\n .graph-palette-overlay {\n position: absolute;\n top: 16px;\n left: 16px;\n display: flex;\n gap: 4px;\n z-index: 10;\n background: rgba(255, 255, 255, 0.95);\n padding: 6px;\n border-radius: var(--radius-md, 8px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(4px);\n }\n\n .palette-item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n padding: 0;\n border: 1.5px solid var(--neutral-200, #e5e7eb);\n border-radius: var(--radius-md, 8px);\n background: var(--white, #fff);\n color: var(--neutral-600, #4b5563);\n cursor: pointer;\n user-select: none;\n transition: all 0.15s ease;\n font-size: 20px;\n }\n\n .palette-item:focus-visible {\n outline: 2px solid var(--indigo-400, #818cf8);\n outline-offset: 2px;\n }\n\n .palette-item:hover {\n background: var(--neutral-50, #f9fafb);\n border-color: var(--interactive, #3b82f6);\n color: var(--interactive, #3b82f6);\n transform: translateY(-1px);\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);\n }\n\n .palette-item:active {\n transform: translateY(0);\n box-shadow: none;\n }\n\n .palette-item.tool-item.active {\n background: var(--interactive, #3b82f6);\n border-color: var(--interactive, #3b82f6);\n color: white;\n }\n\n .palette-item.tool-item.active:hover {\n background: var(--interactive-hover, #2563eb);\n border-color: var(--interactive-hover, #2563eb);\n color: white;\n }\n\n .palette-divider {\n width: 1px;\n background: var(--neutral-200, #e5e7eb);\n align-self: stretch;\n margin: 4px 2px;\n }\n\n .graph-canvas-wrapper {\n flex: 1;\n position: relative;\n overflow: hidden;\n }\n\n .graph-canvas {\n width: 100%;\n height: 100%;\n cursor: grab;\n }\n\n .graph-canvas:active {\n cursor: grabbing;\n }\n\n .graph-canvas.tool-line {\n cursor: crosshair;\n }\n\n .graph-canvas.tool-line .graph-node {\n cursor: crosshair;\n }\n\n .graph-node {\n cursor: move;\n user-select: none;\n -webkit-user-select: none;\n }\n\n .graph-node text {\n pointer-events: none;\n }\n\n .graph-node.selected rect {\n filter: drop-shadow(0 0 6px rgba(59, 130, 246, 0.4));\n }\n\n path.selected {\n stroke: #3b82f6 !important;\n stroke-width: 3 !important;\n }\n\n .edge-hit-area {\n cursor: pointer;\n }\n\n .edge-endpoint {\n cursor: pointer;\n transition: r 0.2s, fill 0.2s;\n }\n\n .edge-endpoint:hover {\n r: 8;\n fill: #2563eb;\n }\n\n .edge-endpoint.selected {\n fill: #2563eb;\n }\n\n .attachment-point {\n cursor: crosshair;\n transition: all 0.2s;\n }\n\n .attachment-point.hovered {\n filter: drop-shadow(0 0 4px rgba(37, 99, 235, 0.6));\n }\n\n .validation-panel {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n max-height: 200px;\n overflow-y: auto;\n background: white;\n border-top: 1px solid #e5e7eb;\n padding: 16px;\n }\n\n .error-item {\n padding: 8px 12px;\n margin-bottom: 8px;\n background: #fee2e2;\n border-left: 3px solid #ef4444;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .error-item.warning {\n background: #fef3c7;\n border-left-color: #f59e0b;\n }\n\n .edge-direction-selector {\n position: absolute;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n display: flex;\n gap: 2px;\n background: rgba(255, 255, 255, 0.95);\n padding: 4px;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n backdrop-filter: blur(4px);\n z-index: 20;\n pointer-events: auto;\n }\n\n .direction-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid #e5e7eb;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.15s;\n color: #6b7280;\n }\n\n .direction-btn:hover {\n background: #f3f4f6;\n border-color: #3b82f6;\n color: #3b82f6;\n }\n\n .direction-btn.active {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class GraphEditorComponent implements OnInit, OnChanges {\n // Inputs\n @Input({ required: true }) config!: GraphEditorConfig;\n @Input() graph: Graph = { nodes: [], edges: [] };\n @Input() readonly = false;\n @Input() visualizationMode = false;\n @Input() overlayData?: Map<string, any>;\n\n // Outputs\n @Output() graphChange = new EventEmitter<Graph>();\n @Output() nodeAdded = new EventEmitter<GraphNode>();\n @Output() nodeUpdated = new EventEmitter<GraphNode>();\n @Output() nodeRemoved = new EventEmitter<GraphNode>();\n @Output() edgeAdded = new EventEmitter<GraphEdge>();\n @Output() edgeUpdated = new EventEmitter<GraphEdge>();\n @Output() edgeRemoved = new EventEmitter<GraphEdge>();\n @Output() selectionChange = new EventEmitter<SelectionState>();\n @Output() validationChange = new EventEmitter<ValidationResult>();\n @Output() nodeClick = new EventEmitter<GraphNode>();\n @Output() nodeDoubleClick = new EventEmitter<GraphNode>();\n @Output() edgeClick = new EventEmitter<GraphEdge>();\n @Output() edgeDoubleClick = new EventEmitter<GraphEdge>();\n @Output() canvasClick = new EventEmitter<Position>();\n @Output() contextMenu = new EventEmitter<ContextMenuEvent>();\n\n private readonly canvasSvgRef = viewChild<ElementRef>('canvasSvg');\n\n // Internal state\n internalGraph = signal<Graph>({ nodes: [], edges: [] });\n selection = signal<SelectionState>({ nodes: [], edges: [] });\n validationResult = signal<ValidationResult | null>(null);\n \n // Pan & Zoom state\n panX = signal(0);\n panY = signal(0);\n scale = signal(1);\n \n // Dragging state\n private draggedNode: GraphNode | null = null;\n private dragOffset: Position = { x: 0, y: 0 };\n private isPanning = false;\n private lastMousePos: Position = { x: 0, y: 0 };\n private draggedEdge: { edge: GraphEdge; endpoint: 'source' | 'target' } | null = null;\n private hoveredNodeId: string | null = null;\n hoveredPort: { nodeId: string; port: 'top' | 'bottom' | 'left' | 'right' } | null = null;\n \n // Attachment points visibility\n showAttachmentPoints = signal<string | null>(null); // nodeId to show ports for\n\n // Active tool\n activeTool = signal<'hand' | 'line'>('hand');\n \n // Line tool state\n private pendingEdge: { sourceId: string; sourcePort: 'top' | 'bottom' | 'left' | 'right' } | null = null;\n\n // Preview line for line tool (rubber-band from source to cursor)\n previewLine = signal<{ source: Position; target: Position } | null>(null);\n\n // Computed\n transform = computed(() => \n `translate(${this.panX()}, ${this.panY()}) scale(${this.scale()})`\n );\n\n gridBounds = computed(() => {\n const gridSize = this.config.canvas?.grid?.size || 20;\n const viewportWidth = 10000; // Large enough to cover any reasonable viewport\n const viewportHeight = 10000;\n \n // Calculate grid offset to align with pan\n const x = Math.floor(-this.panX() / this.scale() / gridSize) * gridSize - viewportWidth / 2;\n const y = Math.floor(-this.panY() / this.scale() / gridSize) * gridSize - viewportHeight / 2;\n \n return {\n x,\n y,\n width: viewportWidth * 2,\n height: viewportHeight * 2\n };\n });\n\n // Selected edge info for direction selector positioning\n selectedEdgeMidpoint = computed(() => {\n const sel = this.selection();\n if (sel.edges.length !== 1) return null;\n const edge = this.internalGraph().edges.find(e => e.id === sel.edges[0]);\n if (!edge) return null;\n\n const sourcePoint = this.getEdgeSourcePoint(edge);\n const targetPoint = this.getEdgeTargetPoint(edge);\n const midX = (sourcePoint.x + targetPoint.x) / 2;\n const midY = (sourcePoint.y + targetPoint.y) / 2;\n\n return {\n edge,\n x: midX * this.scale() + this.panX(),\n y: midY * this.scale() + this.panY()\n };\n });\n\n constructor() {}\n\n ngOnChanges(changes: SimpleChanges) {\n // Sync graph input to internal signal\n if (changes['graph'] && changes['graph'].currentValue) {\n this.internalGraph.set(structuredClone(changes['graph'].currentValue));\n }\n }\n\n ngOnInit() {\n // Initialize with current graph value\n if (this.graph) {\n this.internalGraph.set(structuredClone(this.graph));\n }\n this.validate();\n }\n\n // Node operations\n addNode(type: string, position?: Position): GraphNode {\n const nodeConfig = this.config.nodes.types.find(t => t.type === type);\n if (!nodeConfig) {\n throw new Error(`Unknown node type: ${type}`);\n }\n\n const newNode: GraphNode = {\n id: this.generateId(),\n type,\n data: structuredClone(nodeConfig.defaultData),\n position: position || { x: 100, y: 100 }\n };\n\n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n nodes: [...graph.nodes, newNode]\n });\n\n this.emitGraphChange();\n this.nodeAdded.emit(newNode);\n this.switchTool('hand');\n return newNode;\n }\n\n removeNode(nodeId: string, removeAttachedEdges = false): void {\n const graph = this.internalGraph();\n const removedNode = graph.nodes.find(n => n.id === nodeId);\n this.internalGraph.set({\n ...graph,\n nodes: graph.nodes.filter(n => n.id !== nodeId),\n edges: removeAttachedEdges\n ? graph.edges.filter(e => e.source !== nodeId && e.target !== nodeId)\n : graph.edges\n });\n this.selection.set({ nodes: [], edges: [] });\n this.emitGraphChange();\n if (removedNode) this.nodeRemoved.emit(removedNode);\n }\n\n removeEdge(edgeId: string): void {\n const graph = this.internalGraph();\n const removedEdge = graph.edges.find(e => e.id === edgeId);\n this.internalGraph.set({\n ...graph,\n edges: graph.edges.filter(e => e.id !== edgeId)\n });\n this.selection.set({ nodes: [], edges: [] });\n this.emitGraphChange();\n if (removedEdge) this.edgeRemoved.emit(removedEdge);\n }\n\n updateNode(nodeId: string, updates: Partial<GraphNode>): void {\n const graph = this.internalGraph();\n const nodeIndex = graph.nodes.findIndex(n => n.id === nodeId);\n if (nodeIndex === -1) return;\n\n const updatedNodes = [...graph.nodes];\n updatedNodes[nodeIndex] = { ...updatedNodes[nodeIndex], ...updates };\n \n this.internalGraph.set({\n ...graph,\n nodes: updatedNodes\n });\n this.emitGraphChange();\n }\n\n // Selection\n selectNode(nodeId: string | null): void {\n if (nodeId === null) {\n this.selection.set({ nodes: [], edges: [] });\n } else {\n this.selection.set({ nodes: [nodeId], edges: [] });\n }\n this.selectionChange.emit(this.selection());\n }\n\n selectEdge(edgeId: string | null): void {\n if (edgeId === null) {\n this.selection.set({ nodes: [], edges: [] });\n } else {\n this.selection.set({ nodes: [], edges: [edgeId] });\n }\n this.selectionChange.emit(this.selection());\n }\n\n onKeyDown(event: KeyboardEvent): void {\n if (this.readonly || this.config.interaction?.readonly) return;\n\n // Escape: cancel line drawing, clear selection\n if (event.key === 'Escape') {\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n this.showAttachmentPoints.set(null);\n event.preventDefault();\n return;\n }\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n const sel = this.selection();\n\n // Delete selected edges\n if (sel.edges.length > 0) {\n for (const edgeId of sel.edges) {\n this.removeEdge(edgeId);\n }\n event.preventDefault();\n return;\n }\n\n // Delete selected nodes (keep attached edges)\n if (sel.nodes.length > 0) {\n for (const nodeId of sel.nodes) {\n this.removeNode(nodeId, false);\n }\n event.preventDefault();\n return;\n }\n }\n\n // Arrow keys: nudge selected node(s) — 1px default, 10px with Shift\n if (event.key.startsWith('Arrow')) {\n const sel = this.selection();\n if (sel.nodes.length === 0) return;\n\n const step = event.shiftKey ? 10 : 1;\n let dx = 0;\n let dy = 0;\n switch (event.key) {\n case 'ArrowUp': dy = -step; break;\n case 'ArrowDown': dy = step; break;\n case 'ArrowLeft': dx = -step; break;\n case 'ArrowRight': dx = step; break;\n }\n\n event.preventDefault();\n\n const graph = this.internalGraph();\n const updatedNodes = [...graph.nodes];\n for (const nodeId of sel.nodes) {\n const idx = updatedNodes.findIndex(n => n.id === nodeId);\n if (idx === -1) continue;\n const pos = updatedNodes[idx].position;\n updatedNodes[idx] = { ...updatedNodes[idx], position: { x: pos.x + dx, y: pos.y + dy } };\n }\n\n // Recalculate edge ports for moved nodes (atomic update)\n const movedIds = new Set(sel.nodes);\n const updatedEdges = graph.edges.map(edge => {\n if (!movedIds.has(edge.source) && !movedIds.has(edge.target)) return edge;\n const sourceNode = updatedNodes.find(n => n.id === edge.source);\n const targetNode = updatedNodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n\n this.internalGraph.set({ ...graph, nodes: updatedNodes, edges: updatedEdges });\n this.emitGraphChange();\n }\n }\n\n switchTool(tool: 'hand' | 'line'): void {\n const previousTool = this.activeTool();\n\n // Cancel any in-progress line drawing\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n\n // Preserve node selection when switching hand → line\n if (!(previousTool === 'hand' && tool === 'line')) {\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n }\n\n this.activeTool.set(tool);\n\n // Hand → line with a node selected: start edge from that node\n if (previousTool === 'hand' && tool === 'line') {\n const sel = this.selection();\n if (sel.nodes.length === 1) {\n this.pendingEdge = { sourceId: sel.nodes[0], sourcePort: 'bottom' };\n }\n }\n }\n\n /** @deprecated Use switchTool('line') instead */\n switchToLineTool(): void {\n this.switchTool('line');\n }\n\n onEdgeClick(event: MouseEvent, edge: GraphEdge): void {\n if (this.activeTool() !== 'hand') return;\n event.stopPropagation();\n this.selectEdge(edge.id);\n this.edgeClick.emit(edge);\n }\n\n onEdgeDoubleClick(event: MouseEvent, edge: GraphEdge): void {\n if (this.activeTool() !== 'hand') return;\n event.stopPropagation();\n this.selectEdge(edge.id);\n this.edgeDoubleClick.emit(edge);\n }\n\n clearSelection(): void {\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n }\n\n // Validation\n validate(): ValidationResult {\n if (!this.config.validation) {\n const result = { valid: true, errors: [] };\n this.validationResult.set(result);\n return result;\n }\n\n const errors = this.config.validation!.validators.flatMap(rule =>\n rule.validator(this.internalGraph(), this.config)\n );\n\n const result = {\n valid: errors.filter(e => e.severity !== 'warning').length === 0,\n errors\n };\n\n this.validationResult.set(result);\n this.validationChange.emit(result);\n return result;\n }\n\n // Layout\n async applyLayout(direction: 'TB' | 'LR' = 'TB'): Promise<void> {\n const graph = this.internalGraph();\n if (graph.nodes.length === 0) return;\n\n // Dynamic import to avoid compile-time module resolution issues\n const dagreModule = await import('dagre');\n const dagre = dagreModule.default ?? dagreModule;\n\n const g = new dagre.graphlib.Graph();\n g.setGraph({\n rankdir: direction,\n nodesep: 60,\n ranksep: 80,\n marginx: 40,\n marginy: 40,\n });\n g.setDefaultEdgeLabel(() => ({}));\n\n for (const node of graph.nodes) {\n const size = this.getNodeSize(node);\n g.setNode(node.id, { width: size.width, height: size.height });\n }\n\n for (const edge of graph.edges) {\n g.setEdge(edge.source, edge.target);\n }\n\n dagre.layout(g);\n\n const updatedNodes = graph.nodes.map(node => {\n const dagreNode = g.node(node.id);\n if (!dagreNode) return node;\n const size = this.getNodeSize(node);\n return {\n ...node,\n position: {\n x: dagreNode.x - size.width / 2,\n y: dagreNode.y - size.height / 2,\n },\n };\n });\n\n this.internalGraph.set({ ...graph, nodes: updatedNodes });\n this.emitGraphChange();\n\n setTimeout(() => this.fitToScreen());\n }\n\n fitToScreen(padding = 40): void {\n const nodes = this.internalGraph().nodes;\n if (nodes.length === 0) return;\n\n // Get SVG element dimensions\n const ref = this.canvasSvgRef();\n const svgEl: SVGSVGElement | null = ref?.nativeElement ?? ref ?? null;\n if (!svgEl || typeof svgEl.getBoundingClientRect !== 'function') return;\n\n const rect = svgEl.getBoundingClientRect();\n const viewW = rect.width;\n const viewH = rect.height;\n if (viewW === 0 || viewH === 0) return;\n\n // Calculate bounding box of all nodes\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const node of nodes) {\n const size = this.getNodeSize(node);\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n const contentW = maxX - minX;\n const contentH = maxY - minY;\n\n // Handle single node or all nodes stacked\n if (contentW <= 0 && contentH <= 0) {\n this.scale.set(1);\n this.panX.set(viewW / 2 - (minX + 110) * 1);\n this.panY.set(viewH / 2 - (minY + 50) * 1);\n return;\n }\n\n // Calculate scale to fit content with padding (cap at 1 to avoid zooming in too much)\n const zoomConfig = this.config.canvas?.zoom;\n const minScale = zoomConfig?.min ?? 0.25;\n const scaleX = contentW > 0 ? (viewW - padding * 2) / contentW : 1;\n const scaleY = contentH > 0 ? (viewH - padding * 2) / contentH : 1;\n const newScale = Math.max(minScale, Math.min(1, Math.min(scaleX, scaleY)));\n\n // Center the content in the viewport\n const centerX = (minX + maxX) / 2;\n const centerY = (minY + maxY) / 2;\n const newPanX = viewW / 2 - centerX * newScale;\n const newPanY = viewH / 2 - centerY * newScale;\n\n this.scale.set(newScale);\n this.panX.set(newPanX);\n this.panY.set(newPanY);\n }\n\n zoomTo(level: number): void {\n const zoomConfig = this.config.canvas?.zoom;\n const min = zoomConfig?.min ?? 0.25;\n const max = zoomConfig?.max ?? 2.0;\n this.scale.set(Math.max(min, Math.min(max, level)));\n }\n\n getSelection(): SelectionState {\n return this.selection();\n }\n\n // Event handlers\n onCanvasMouseDown(event: MouseEvent): void {\n if (this.readonly) return;\n \n // Cancel pending edge on empty space click\n if (this.pendingEdge) {\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n \n const target = event.target as SVGElement;\n const isNode = !!target.closest('.graph-node');\n const isEdgeEndpoint = target.classList.contains('edge-endpoint');\n const isAttachmentPoint = target.classList.contains('attachment-point');\n const isHitArea = target.classList.contains('edge-hit-area');\n const isInteractive = isNode || isEdgeEndpoint || isAttachmentPoint || isHitArea;\n\n if (!isInteractive) {\n this.isPanning = true;\n this.lastMousePos = { x: event.clientX, y: event.clientY };\n this.clearSelection();\n event.preventDefault();\n }\n }\n\n onCanvasMouseMove(event: MouseEvent): void {\n if (this.isPanning) {\n const dx = event.clientX - this.lastMousePos.x;\n const dy = event.clientY - this.lastMousePos.y;\n this.panX.set(this.panX() + dx);\n this.panY.set(this.panY() + dy);\n this.lastMousePos = { x: event.clientX, y: event.clientY };\n } else if (this.draggedNode) {\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n let x = mouseX - this.dragOffset.x;\n let y = mouseY - this.dragOffset.y;\n \n // Smart snap to grid\n if (this.config.canvas?.grid?.snap) {\n const gridSize = this.config.canvas.grid.size || 20;\n const snapThreshold = gridSize / 4;\n \n const snapX = Math.round(x / gridSize) * gridSize;\n const snapY = Math.round(y / gridSize) * gridSize;\n \n if (Math.abs(x - snapX) < snapThreshold) x = snapX;\n if (Math.abs(y - snapY) < snapThreshold) y = snapY;\n }\n \n // Atomic update: node position + edge port recalculation in one graph set\n const graph = this.internalGraph();\n const nodeIndex = graph.nodes.findIndex(n => n.id === this.draggedNode!.id);\n if (nodeIndex !== -1) {\n const updatedNodes = [...graph.nodes];\n updatedNodes[nodeIndex] = { ...updatedNodes[nodeIndex], position: { x, y } };\n \n // Recalculate ports for all edges connected to this node\n const draggedId = this.draggedNode.id;\n const updatedEdges = graph.edges.map(edge => {\n if (edge.source !== draggedId && edge.target !== draggedId) return edge;\n const sourceNode = updatedNodes.find(n => n.id === edge.source);\n const targetNode = updatedNodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n \n this.internalGraph.set({ ...graph, nodes: updatedNodes, edges: updatedEdges });\n this.emitGraphChange();\n }\n } else if (this.draggedEdge) {\n // Edge reconnection - find hovered node and closest port\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n \n // Find node under cursor\n const nodeId = this.findNodeAtPosition({ x: mouseX, y: mouseY });\n \n if (nodeId) {\n // Show attachment points for this node\n this.showAttachmentPoints.set(nodeId);\n \n // Find closest port\n const closestPort = this.findClosestPort(nodeId, { x: mouseX, y: mouseY });\n \n // Highlight port if within snap distance (40px)\n if (closestPort && closestPort.distance < 40) {\n this.hoveredPort = { nodeId, port: closestPort.port };\n this.hoveredNodeId = nodeId;\n } else {\n this.hoveredPort = null;\n this.hoveredNodeId = null;\n }\n } else {\n // No node nearby - hide attachment points\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.hoveredNodeId = null;\n }\n } else if (this.pendingEdge && this.activeTool() === 'line') {\n // Line tool pending state - show rubber-band preview + attachment points on hovered node\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n \n // Get source port position\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePoint = this.getPortWorldPosition(sourceNode, this.pendingEdge.sourcePort);\n \n // Check if cursor is near a node - snap to its closest port\n const hoveredNodeId = this.findNodeAtPosition({ x: mouseX, y: mouseY });\n let targetPoint: Position = { x: mouseX, y: mouseY };\n \n if (hoveredNodeId && hoveredNodeId !== this.pendingEdge.sourceId) {\n // Show attachment points on hovered node\n this.showAttachmentPoints.set(hoveredNodeId);\n \n // Find and highlight closest port\n const closestPort = this.findClosestPort(hoveredNodeId, { x: mouseX, y: mouseY });\n if (closestPort && closestPort.distance < 40) {\n this.hoveredPort = { nodeId: hoveredNodeId, port: closestPort.port };\n // Snap preview line to port\n const hoveredNode = this.internalGraph().nodes.find(n => n.id === hoveredNodeId);\n if (hoveredNode) {\n targetPoint = this.getPortWorldPosition(hoveredNode, closestPort.port);\n }\n } else {\n this.hoveredPort = null;\n }\n } else {\n // Not over a valid target node - hide attachment points\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n }\n \n this.previewLine.set({ source: sourcePoint, target: targetPoint });\n }\n }\n }\n\n onCanvasMouseUp(_event: MouseEvent): void {\n // Handle edge reconnection with port snapping\n if (this.draggedEdge && this.hoveredNodeId && this.hoveredPort) {\n const graph = this.internalGraph();\n const edgeIndex = graph.edges.findIndex(e => e.id === this.draggedEdge!.edge.id);\n \n if (edgeIndex !== -1) {\n const updatedEdges = [...graph.edges];\n const updatedEdge = { ...updatedEdges[edgeIndex] };\n \n // Update node connection and store port information (non-null: guarded by if condition)\n if (this.draggedEdge.endpoint === 'source') {\n updatedEdge.source = this.hoveredNodeId!;\n updatedEdge.sourcePort = this.hoveredPort!.port;\n } else {\n updatedEdge.target = this.hoveredNodeId!;\n updatedEdge.targetPort = this.hoveredPort!.port;\n }\n \n updatedEdges[edgeIndex] = updatedEdge;\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n this.emitGraphChange();\n this.edgeUpdated.emit(updatedEdge);\n }\n }\n \n this.isPanning = false;\n this.draggedNode = null;\n this.draggedEdge = null;\n this.hoveredNodeId = null;\n this.hoveredPort = null;\n this.showAttachmentPoints.set(null);\n }\n\n onNodeMouseDown(event: MouseEvent, node: GraphNode): void {\n if (this.readonly) return;\n event.stopPropagation(); // Always prevent canvas from seeing node mousedowns\n if (this.activeTool() !== 'hand') return;\n \n this.draggedNode = node;\n \n // Calculate offset between mouse position and node origin to prevent jump\n const svg = (event.target as SVGElement).closest('svg')!;\n const rect = svg.getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n this.dragOffset = {\n x: mouseX - node.position.x,\n y: mouseY - node.position.y\n };\n }\n\n onNodeClick(event: MouseEvent, node: GraphNode): void {\n if (this.activeTool() === 'line') {\n event.stopPropagation();\n \n if (!this.pendingEdge) {\n // First click - start edge from this node\n // Pick initial port based on geometry (will be recalculated on second click)\n this.pendingEdge = { sourceId: node.id, sourcePort: 'bottom' };\n this.selectNode(node.id);\n } else if (this.pendingEdge.sourceId !== node.id) {\n // Second click on different node - complete the edge\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePort = this.findClosestPortForEdge(sourceNode, node, 'source');\n const targetPort = this.findClosestPortForEdge(node, sourceNode, 'target');\n \n const newEdge: GraphEdge = {\n id: `edge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n source: this.pendingEdge.sourceId,\n target: node.id,\n sourcePort,\n targetPort\n };\n \n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n edges: [...graph.edges, newEdge]\n });\n this.emitGraphChange();\n this.edgeAdded.emit(newEdge);\n }\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n } else {\n // Clicked same node - cancel\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n } else {\n // Hand tool - normal select\n this.selectNode(node.id);\n }\n }\n\n onAttachmentPointClick(event: MouseEvent, node: GraphNode, port: 'top' | 'bottom' | 'left' | 'right'): void {\n event.stopPropagation();\n if (this.readonly) return;\n \n if (this.activeTool() === 'line') {\n if (!this.pendingEdge) {\n // First click on attachment point - start edge from this specific port\n this.pendingEdge = { sourceId: node.id, sourcePort: port };\n this.selectNode(node.id);\n } else if (this.pendingEdge.sourceId !== node.id) {\n // Second click - complete edge to this specific port\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePort = this.findClosestPortForEdge(sourceNode, node, 'source');\n \n const newEdge: GraphEdge = {\n id: `edge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n source: this.pendingEdge.sourceId,\n target: node.id,\n sourcePort,\n targetPort: port\n };\n \n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n edges: [...graph.edges, newEdge]\n });\n this.emitGraphChange();\n this.edgeAdded.emit(newEdge);\n }\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n } else {\n // Clicked same node - cancel\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n }\n }\n\n onEdgeEndpointMouseDown(event: MouseEvent, edge: GraphEdge, endpoint: 'source' | 'target'): void {\n if (this.readonly) return;\n event.stopPropagation();\n this.draggedEdge = { edge, endpoint };\n }\n\n onWheel(event: WheelEvent): void {\n const zoomConfig = this.config.canvas?.zoom;\n if (!zoomConfig?.wheelEnabled) return;\n\n event.preventDefault();\n const delta = -event.deltaY;\n const step = zoomConfig.step ?? 0.1;\n const newScale = Math.max(\n zoomConfig.min ?? 0.25,\n Math.min(\n zoomConfig.max ?? 2.0,\n this.scale() + (delta > 0 ? step : -step)\n )\n );\n \n this.scale.set(newScale);\n }\n\n onContextMenu(event: MouseEvent): void {\n event.preventDefault();\n // TODO: Show context menu\n }\n\n // Helper methods\n private emitGraphChange(): void {\n this.graphChange.emit(this.internalGraph());\n if (this.config.validation?.validateOnChange) {\n this.validate();\n }\n }\n\n private generateId(): string {\n return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private recalculateEdgePorts(nodeId: string): void {\n const graph = this.internalGraph();\n let changed = false;\n const updatedEdges = graph.edges.map(edge => {\n if (edge.source !== nodeId && edge.target !== nodeId) return edge;\n \n const sourceNode = graph.nodes.find(n => n.id === edge.source);\n const targetNode = graph.nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n \n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n \n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n \n changed = true;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n \n if (changed) {\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n }\n }\n\n getNodeSize(node: GraphNode): { width: number; height: number } {\n const nodeConfig = this.config.nodes.types.find(t => t.type === node.type);\n return nodeConfig?.size || this.config.nodes.defaultSize || { width: 220, height: 100 };\n }\n\n getEdgePath(edge: GraphEdge): string {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n \n if (!sourceNode || !targetNode) return '';\n\n // Get port positions from edge or calculate closest\n const sourcePort = (edge.sourcePort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const targetPort = (edge.targetPort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n \n const sourcePoint = this.getPortWorldPosition(sourceNode, sourcePort);\n const targetPoint = this.getPortWorldPosition(targetNode, targetPort);\n\n // Simple straight line\n return `M ${sourcePoint.x},${sourcePoint.y} L ${targetPoint.x},${targetPoint.y}`;\n }\n\n getEdgeColor(edge: GraphEdge): string {\n return edge.metadata?.style?.stroke || this.config.edges.style?.stroke || '#94a3b8';\n }\n\n getEdgeMarkerEnd(edge: GraphEdge): string | null {\n const dir = edge.direction || 'forward';\n const selected = this.selection().edges.includes(edge.id);\n if (dir === 'forward' || dir === 'bidirectional') {\n return selected ? 'url(#arrow-end-selected)' : 'url(#arrow-end)';\n }\n return null;\n }\n\n getEdgeMarkerStart(edge: GraphEdge): string | null {\n const dir = edge.direction || 'forward';\n const selected = this.selection().edges.includes(edge.id);\n if (dir === 'backward' || dir === 'bidirectional') {\n return selected ? 'url(#arrow-start-selected)' : 'url(#arrow-start)';\n }\n return null;\n }\n\n setEdgeDirection(direction: 'forward' | 'backward' | 'bidirectional'): void {\n const sel = this.selection();\n if (sel.edges.length !== 1) return;\n \n const graph = this.internalGraph();\n const edgeIndex = graph.edges.findIndex(e => e.id === sel.edges[0]);\n if (edgeIndex === -1) return;\n \n const updatedEdges = [...graph.edges];\n updatedEdges[edgeIndex] = { ...updatedEdges[edgeIndex], direction };\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n this.emitGraphChange();\n this.edgeUpdated.emit(updatedEdges[edgeIndex]);\n }\n\n getEdgeSourcePoint(edge: GraphEdge): Position {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return { x: 0, y: 0 };\n \n const sourcePort = (edge.sourcePort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n return this.getPortWorldPosition(sourceNode, sourcePort);\n }\n\n getEdgeTargetPoint(edge: GraphEdge): Position {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return { x: 0, y: 0 };\n \n const targetPort = (edge.targetPort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n return this.getPortWorldPosition(targetNode, targetPort);\n }\n\n getNodeTypeIcon(node: GraphNode): string {\n const nodeConfig = this.config.nodes.types.find(t => t.type === node.type);\n return nodeConfig?.icon || '●';\n }\n\n private findNodeAtPosition(pos: Position): string | null {\n for (const node of this.internalGraph().nodes) {\n const size = this.getNodeSize(node);\n if (\n pos.x >= node.position.x &&\n pos.x <= node.position.x + size.width &&\n pos.y >= node.position.y &&\n pos.y <= node.position.y + size.height\n ) {\n return node.id;\n }\n }\n return null;\n }\n\n getNodePorts(node: GraphNode): Array<{ position: 'top' | 'bottom' | 'left' | 'right'; x: number; y: number }> {\n const size = this.getNodeSize(node);\n return [\n { position: 'top', x: size.width / 2, y: 0 },\n { position: 'bottom', x: size.width / 2, y: size.height },\n { position: 'left', x: 0, y: size.height / 2 },\n { position: 'right', x: size.width, y: size.height / 2 }\n ];\n }\n\n private findClosestPort(nodeId: string, worldPos: Position): { port: 'top' | 'bottom' | 'left' | 'right'; distance: number } | null {\n const node = this.internalGraph().nodes.find(n => n.id === nodeId);\n if (!node) return null;\n \n const ports = this.getNodePorts(node);\n let closestPort: typeof ports[0] | null = null;\n let minDistance = Infinity;\n \n for (const port of ports) {\n const portWorldX = node.position.x + port.x;\n const portWorldY = node.position.y + port.y;\n const dx = worldPos.x - portWorldX;\n const dy = worldPos.y - portWorldY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < minDistance) {\n minDistance = distance;\n closestPort = port;\n }\n }\n \n return closestPort ? { port: closestPort.position, distance: minDistance } : null;\n }\n\n private getPortWorldPosition(node: GraphNode, port: 'top' | 'bottom' | 'left' | 'right'): Position {\n const size = this.getNodeSize(node);\n const portOffsets = {\n top: { x: size.width / 2, y: 0 },\n bottom: { x: size.width / 2, y: size.height },\n left: { x: 0, y: size.height / 2 },\n right: { x: size.width, y: size.height / 2 }\n };\n \n const offset = portOffsets[port];\n return {\n x: node.position.x + offset.x,\n y: node.position.y + offset.y\n };\n }\n\n private findClosestPortForEdge(\n node: GraphNode,\n otherNode: GraphNode,\n endpoint: 'source' | 'target'\n ): 'top' | 'bottom' | 'left' | 'right' {\n const size = this.getNodeSize(node);\n const nodeCenter = {\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2\n };\n const otherSize = this.getNodeSize(otherNode);\n const otherCenter = {\n x: otherNode.position.x + otherSize.width / 2,\n y: otherNode.position.y + otherSize.height / 2\n };\n \n const dx = otherCenter.x - nodeCenter.x;\n const dy = otherCenter.y - nodeCenter.y;\n \n // Determine which port is closest based on relative position\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n \n if (absDx > absDy) {\n // Horizontal connection\n return dx > 0 ? 'right' : 'left';\n } else {\n // Vertical connection\n return dy > 0 ? 'bottom' : 'top';\n }\n }\n}\n","// Main component\nexport { GraphEditorComponent } from './lib/graph-editor.component';\n\n// Data model - use 'export type' for re-exports when isolatedModules is enabled\nexport type {\n Graph,\n GraphNode,\n GraphEdge,\n Position,\n NodeMetadata,\n EdgeMetadata,\n EdgeStyle,\n GraphMetadata\n} from './lib/graph.model';\n\n// Configuration - use 'export type' for re-exports\nexport type {\n GraphEditorConfig,\n NodesConfig,\n EdgesConfig,\n CanvasConfig,\n ValidationConfig,\n LayoutConfig,\n InteractionConfig,\n ThemeConfig,\n PaletteConfig,\n NodeTypeDefinition,\n PortConfig,\n PortDefinition,\n NodeConstraints,\n GridConfig,\n ZoomConfig,\n PanConfig,\n ValidationRule,\n ValidationError,\n LayoutOptions,\n ContextMenuConfig,\n ContextMenuItem,\n ContextMenuContext,\n SelectionState,\n ValidationResult,\n ContextMenuEvent\n} from './lib/graph-editor.config';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utisha-graph-editor.mjs","sources":["../../../projects/graph-editor/src/lib/graph-editor.component.ts","../../../projects/graph-editor/src/public-api.ts","../../../projects/graph-editor/src/utisha-graph-editor.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n OnInit,\n Output,\n signal,\n SimpleChanges,\n viewChild\n} from '@angular/core';\n// dagre is loaded dynamically in applyLayout() to avoid compile-time resolution issues\nimport {Graph, GraphEdge, GraphNode, Position} from './graph.model';\nimport {ContextMenuEvent, GraphEditorConfig, SelectionState, ValidationResult} from './graph-editor.config';\n\n/**\n * Main graph editor component.\n *\n * @example\n * <graph-editor\n * [config]=\"editorConfig\"\n * [graph]=\"currentGraph()\"\n * (graphChange)=\"onGraphChange($event)\"\n * />\n */\n@Component({\n selector: 'graph-editor',\n standalone: true,\n imports: [],\n host: {\n 'tabindex': '0',\n 'style': 'outline: none;',\n '(keydown)': 'onKeyDown($event)'\n },\n template: `\n <div class=\"graph-editor-container\">\n <!-- Canvas with overlaid palette -->\n <div class=\"graph-canvas-wrapper\">\n <!-- Top-left horizontal palette overlay -->\n @if (config.palette?.enabled !== false) {\n <div class=\"graph-palette-overlay\">\n <!-- Tools -->\n <button\n class=\"palette-item tool-item\"\n [class.active]=\"activeTool() === 'hand'\"\n title=\"Hand tool (move nodes)\"\n (click)=\"switchTool('hand')\"\n >\n <span class=\"icon\">✋</span>\n </button>\n <button\n class=\"palette-item tool-item\"\n [class.active]=\"activeTool() === 'line'\"\n title=\"Line tool (draw connections)\"\n (click)=\"switchTool('line')\"\n >\n <span class=\"icon\">∕</span>\n </button>\n\n <!-- Divider -->\n <div class=\"palette-divider\"></div>\n\n <!-- Node types -->\n @for (nodeType of config.nodes.types; track nodeType.type) {\n <button\n class=\"palette-item\"\n [attr.data-node-type]=\"nodeType.type\"\n [attr.title]=\"nodeType.label || nodeType.type\"\n (click)=\"addNode(nodeType.type)\"\n >\n <span class=\"icon\">{{ nodeType.icon || '●' }}</span>\n </button>\n }\n </div>\n }\n\n <svg\n #canvasSvg\n [class.tool-line]=\"activeTool() === 'line'\"\n [attr.width]=\"'100%'\"\n [attr.height]=\"'100%'\"\n (mousedown)=\"onCanvasMouseDown($event)\"\n (mousemove)=\"onCanvasMouseMove($event)\"\n (mouseup)=\"onCanvasMouseUp($event)\"\n (wheel)=\"onWheel($event)\"\n (contextmenu)=\"onContextMenu($event)\"\n >\n <!-- Arrow marker definitions -->\n <defs>\n <marker id=\"arrow-end\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 0 1 L 8 5 L 0 9 z\" fill=\"#94a3b8\"/>\n </marker>\n <marker id=\"arrow-end-selected\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 0 1 L 8 5 L 0 9 z\" fill=\"#3b82f6\"/>\n </marker>\n <marker id=\"arrow-start\" viewBox=\"0 0 10 10\" refX=\"1\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 10 1 L 2 5 L 10 9 z\" fill=\"#94a3b8\"/>\n </marker>\n <marker id=\"arrow-start-selected\" viewBox=\"0 0 10 10\" refX=\"1\" refY=\"5\"\n markerWidth=\"8\" markerHeight=\"8\" orient=\"auto\">\n <path d=\"M 10 1 L 2 5 L 10 9 z\" fill=\"#3b82f6\"/>\n </marker>\n </defs>\n\n <!-- Main transform group (pan + zoom) -->\n <g [attr.transform]=\"transform()\">\n <!-- Grid (if enabled) -->\n <!-- Grid (if enabled) - extended to cover viewport during pan -->\n @if (config.canvas?.grid?.enabled) {\n <defs>\n <pattern\n id=\"grid\"\n [attr.width]=\"config.canvas!.grid!.size\"\n [attr.height]=\"config.canvas!.grid!.size\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n [attr.d]=\"'M ' + config.canvas!.grid!.size + ' 0 L 0 0 0 ' + config.canvas!.grid!.size\"\n fill=\"none\"\n [attr.stroke]=\"config.canvas!.grid!.color || '#e0e0e0'\"\n stroke-width=\"1\"\n />\n </pattern>\n </defs>\n <!-- Extended grid background covering viewport + pan offset -->\n <rect\n [attr.x]=\"gridBounds().x\"\n [attr.y]=\"gridBounds().y\"\n [attr.width]=\"gridBounds().width\"\n [attr.height]=\"gridBounds().height\"\n fill=\"url(#grid)\"\n />\n }\n\n <!-- Layer 0.5: Preview line for line tool (rubber-band) -->\n @if (previewLine()) {\n <line\n class=\"preview-line\"\n [attr.x1]=\"previewLine()!.source.x\"\n [attr.y1]=\"previewLine()!.source.y\"\n [attr.x2]=\"previewLine()!.target.x\"\n [attr.y2]=\"previewLine()!.target.y\"\n stroke=\"#3b82f6\"\n stroke-width=\"2.5\"\n stroke-dasharray=\"8,6\"\n stroke-linecap=\"round\"\n opacity=\"0.7\"\n />\n }\n\n <!-- Layer 1: Edge paths (behind everything) -->\n @for (edge of internalGraph().edges; track edge.id) {\n <!-- Edge shadow for depth (optional) -->\n @if (shadowsEnabled()) {\n <path\n class=\"edge-shadow\"\n [attr.d]=\"getEdgePath(edge)\"\n stroke=\"rgba(0,0,0,0.06)\"\n stroke-width=\"6\"\n fill=\"none\"\n stroke-linecap=\"round\"\n [attr.transform]=\"'translate(1, 2)'\"\n />\n }\n <!-- Invisible wide hit-area for easier clicking (hand tool only) -->\n <path\n [attr.d]=\"getEdgePath(edge)\"\n stroke=\"transparent\"\n [attr.stroke-width]=\"20\"\n fill=\"none\"\n class=\"edge-hit-area\"\n [attr.pointer-events]=\"activeTool() === 'hand' ? 'stroke' : 'none'\"\n (click)=\"onEdgeClick($event, edge)\"\n (dblclick)=\"onEdgeDoubleClick($event, edge)\"\n />\n <!-- Visible edge line -->\n <path\n class=\"edge-line\"\n [attr.d]=\"getEdgePath(edge)\"\n [attr.stroke]=\"selection().edges.includes(edge.id) ? '#3b82f6' : '#94a3b8'\"\n [attr.stroke-width]=\"selection().edges.includes(edge.id) ? 2.5 : 2\"\n fill=\"none\"\n stroke-linecap=\"round\"\n [class.selected]=\"selection().edges.includes(edge.id)\"\n [attr.marker-end]=\"getEdgeMarkerEnd(edge)\"\n [attr.marker-start]=\"getEdgeMarkerStart(edge)\"\n pointer-events=\"none\"\n />\n }\n\n <!-- Layer 2: Nodes -->\n @for (node of internalGraph().nodes; track node.id) {\n <g\n [attr.transform]=\"'translate(' + node.position.x + ',' + node.position.y + ')'\"\n class=\"graph-node\"\n [class.selected]=\"selection().nodes.includes(node.id)\"\n [attr.data-node-id]=\"node.id\"\n (mousedown)=\"onNodeMouseDown($event, node)\"\n (click)=\"onNodeClick($event, node)\"\n (dblclick)=\"nodeDoubleClick.emit(node)\"\n >\n <!-- Node shadow (optional) -->\n @if (shadowsEnabled()) {\n <rect\n class=\"node-shadow\"\n [attr.width]=\"getNodeSize(node).width\"\n [attr.height]=\"getNodeSize(node).height\"\n fill=\"rgba(0,0,0,0.08)\"\n rx=\"12\"\n transform=\"translate(2, 3)\"\n style=\"filter: blur(4px);\"\n />\n }\n <!-- Node background -->\n <rect\n class=\"node-bg\"\n [attr.width]=\"getNodeSize(node).width\"\n [attr.height]=\"getNodeSize(node).height\"\n fill=\"white\"\n [attr.stroke]=\"selection().nodes.includes(node.id) ? '#3b82f6' : '#e2e8f0'\"\n [attr.stroke-width]=\"selection().nodes.includes(node.id) ? 2.5 : 1.5\"\n rx=\"12\"\n />\n\n <!-- Node type icon -->\n <text\n class=\"node-icon\"\n [attr.x]=\"getIconPosition(node).x\"\n [attr.y]=\"getIconPosition(node).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n [attr.font-size]=\"getNodeSize(node).height * 0.28\"\n >\n {{ getNodeTypeIcon(node) }}\n </text>\n\n <!-- Node label -->\n <text\n class=\"node-label\"\n [attr.x]=\"getLabelPosition(node).x\"\n [attr.y]=\"getLabelPosition(node).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-size=\"14\"\n font-weight=\"500\"\n fill=\"#1e293b\"\n >\n {{ node.data['name'] || node.type }}\n </text>\n </g>\n }\n\n <!-- Layer 3: Attachment points (on top of nodes) -->\n @for (node of internalGraph().nodes; track node.id) {\n @if (showAttachmentPoints() === node.id) {\n <g [attr.transform]=\"'translate(' + node.position.x + ',' + node.position.y + ')'\">\n @for (port of getNodePorts(node); track port.position) {\n <circle\n [attr.cx]=\"port.x\"\n [attr.cy]=\"port.y\"\n [attr.r]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position ? 8 : 6\"\n [attr.fill]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position ? '#2563eb' : '#94a3b8'\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"attachment-point\"\n [class.hovered]=\"hoveredPort?.nodeId === node.id && hoveredPort?.port === port.position\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"onAttachmentPointClick($event, node, port.position)\"\n />\n }\n </g>\n }\n }\n\n <!-- Layer 4: Edge endpoints (only visible when edge is selected) -->\n @for (edge of internalGraph().edges; track edge.id) {\n @if (selection().edges.includes(edge.id)) {\n <g>\n <!-- Source endpoint -->\n <circle\n [attr.cx]=\"getEdgeSourcePoint(edge).x\"\n [attr.cy]=\"getEdgeSourcePoint(edge).y\"\n r=\"6\"\n fill=\"#3b82f6\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"edge-endpoint selected\"\n (mousedown)=\"onEdgeEndpointMouseDown($event, edge, 'source')\"\n />\n\n <!-- Target endpoint -->\n <circle\n [attr.cx]=\"getEdgeTargetPoint(edge).x\"\n [attr.cy]=\"getEdgeTargetPoint(edge).y\"\n r=\"6\"\n fill=\"#3b82f6\"\n stroke=\"white\"\n stroke-width=\"2\"\n class=\"edge-endpoint selected\"\n (mousedown)=\"onEdgeEndpointMouseDown($event, edge, 'target')\"\n />\n </g>\n }\n }\n </g>\n </svg>\n </div>\n\n <!-- Edge direction selector overlay -->\n @if (selectedEdgeMidpoint()) {\n <div\n class=\"edge-direction-selector\"\n [style.left.px]=\"selectedEdgeMidpoint()!.x\"\n [style.top.px]=\"selectedEdgeMidpoint()!.y\"\n >\n <button\n class=\"direction-btn\"\n [class.active]=\"selectedEdgeMidpoint()!.edge.direction === 'backward'\"\n title=\"Backward\"\n (click)=\"setEdgeDirection('backward')\"\n >←</button>\n <button\n class=\"direction-btn\"\n [class.active]=\"selectedEdgeMidpoint()!.edge.direction === 'bidirectional'\"\n title=\"Bidirectional\"\n (click)=\"setEdgeDirection('bidirectional')\"\n >↔</button>\n <button\n class=\"direction-btn\"\n [class.active]=\"!selectedEdgeMidpoint()!.edge.direction || selectedEdgeMidpoint()!.edge.direction === 'forward'\"\n title=\"Forward\"\n (click)=\"setEdgeDirection('forward')\"\n >→</button>\n </div>\n }\n <!-- Validation errors -->\n @if (validationResult() && !validationResult()!.valid) {\n <div class=\"validation-panel\">\n <h4>Validation Errors</h4>\n @for (error of validationResult()!.errors; track error.rule) {\n <div class=\"error-item\" [class.warning]=\"error.severity === 'warning'\">\n {{ error.message }}\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .graph-editor-container {\n display: flex;\n width: 100%;\n height: 100%;\n position: relative;\n background: var(--graph-editor-canvas-bg, #f8f9fa);\n }\n\n .graph-palette-overlay {\n position: absolute;\n top: 16px;\n left: 16px;\n display: flex;\n gap: 4px;\n z-index: 10;\n background: rgba(255, 255, 255, 0.95);\n padding: 6px;\n border-radius: var(--radius-md, 8px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(4px);\n }\n\n .palette-item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n padding: 0;\n border: 1.5px solid var(--neutral-200, #e5e7eb);\n border-radius: var(--radius-md, 8px);\n background: var(--white, #fff);\n color: var(--neutral-600, #4b5563);\n cursor: pointer;\n user-select: none;\n transition: all 0.15s ease;\n font-size: 20px;\n }\n\n .palette-item:focus-visible {\n outline: 2px solid var(--indigo-400, #818cf8);\n outline-offset: 2px;\n }\n\n .palette-item:hover {\n background: var(--neutral-50, #f9fafb);\n border-color: var(--interactive, #3b82f6);\n color: var(--interactive, #3b82f6);\n transform: translateY(-1px);\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);\n }\n\n .palette-item:active {\n transform: translateY(0);\n box-shadow: none;\n }\n\n .palette-item.tool-item.active {\n background: var(--interactive, #3b82f6);\n border-color: var(--interactive, #3b82f6);\n color: white;\n }\n\n .palette-item.tool-item.active:hover {\n background: var(--interactive-hover, #2563eb);\n border-color: var(--interactive-hover, #2563eb);\n color: white;\n }\n\n .palette-divider {\n width: 1px;\n background: var(--neutral-200, #e5e7eb);\n align-self: stretch;\n margin: 4px 2px;\n }\n\n .graph-canvas-wrapper {\n flex: 1;\n position: relative;\n overflow: hidden;\n }\n\n .graph-canvas {\n width: 100%;\n height: 100%;\n cursor: grab;\n }\n\n .graph-canvas:active {\n cursor: grabbing;\n }\n\n .graph-canvas.tool-line {\n cursor: crosshair;\n }\n\n .graph-canvas.tool-line .graph-node {\n cursor: crosshair;\n }\n\n .graph-node {\n cursor: move;\n user-select: none;\n -webkit-user-select: none;\n transition: transform 0.1s ease-out;\n }\n\n .graph-node:hover .node-bg {\n stroke: #cbd5e1;\n }\n\n .graph-node text {\n pointer-events: none;\n }\n\n .graph-node .node-label {\n font-family: system-ui, -apple-system, sans-serif;\n }\n\n .graph-node.selected .node-bg {\n stroke: #3b82f6;\n filter: drop-shadow(0 4px 12px rgba(59, 130, 246, 0.25));\n }\n\n\n .edge-line {\n transition: stroke 0.15s, stroke-width 0.15s;\n }\n\n .edge-line.selected {\n filter: drop-shadow(0 2px 4px rgba(59, 130, 246, 0.3));\n }\n\n .edge-hit-area {\n cursor: pointer;\n }\n\n .edge-endpoint {\n cursor: pointer;\n transition: r 0.2s, fill 0.2s;\n }\n\n .edge-endpoint:hover {\n r: 8;\n fill: #2563eb;\n }\n\n .edge-endpoint.selected {\n fill: #2563eb;\n }\n\n .attachment-point {\n cursor: crosshair;\n transition: all 0.2s;\n }\n\n .attachment-point.hovered {\n filter: drop-shadow(0 0 4px rgba(37, 99, 235, 0.6));\n }\n\n .validation-panel {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n max-height: 200px;\n overflow-y: auto;\n background: white;\n border-top: 1px solid #e5e7eb;\n padding: 16px;\n }\n\n .error-item {\n padding: 8px 12px;\n margin-bottom: 8px;\n background: #fee2e2;\n border-left: 3px solid #ef4444;\n border-radius: 4px;\n font-size: 14px;\n }\n\n .error-item.warning {\n background: #fef3c7;\n border-left-color: #f59e0b;\n }\n\n .edge-direction-selector {\n position: absolute;\n transform: translate(-50%, -100%);\n margin-top: -12px;\n display: flex;\n gap: 2px;\n background: rgba(255, 255, 255, 0.95);\n padding: 4px;\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n backdrop-filter: blur(4px);\n z-index: 20;\n pointer-events: auto;\n }\n\n .direction-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid #e5e7eb;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.15s;\n color: #6b7280;\n }\n\n .direction-btn:hover {\n background: #f3f4f6;\n border-color: #3b82f6;\n color: #3b82f6;\n }\n\n .direction-btn.active {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class GraphEditorComponent implements OnInit, OnChanges {\n // Inputs\n @Input({ required: true }) config!: GraphEditorConfig;\n @Input() graph: Graph = { nodes: [], edges: [] };\n @Input() readonly = false;\n @Input() visualizationMode = false;\n @Input() overlayData?: Map<string, any>;\n\n // Outputs\n @Output() graphChange = new EventEmitter<Graph>();\n @Output() nodeAdded = new EventEmitter<GraphNode>();\n @Output() nodeUpdated = new EventEmitter<GraphNode>();\n @Output() nodeRemoved = new EventEmitter<GraphNode>();\n @Output() edgeAdded = new EventEmitter<GraphEdge>();\n @Output() edgeUpdated = new EventEmitter<GraphEdge>();\n @Output() edgeRemoved = new EventEmitter<GraphEdge>();\n @Output() selectionChange = new EventEmitter<SelectionState>();\n @Output() validationChange = new EventEmitter<ValidationResult>();\n @Output() nodeClick = new EventEmitter<GraphNode>();\n @Output() nodeDoubleClick = new EventEmitter<GraphNode>();\n @Output() edgeClick = new EventEmitter<GraphEdge>();\n @Output() edgeDoubleClick = new EventEmitter<GraphEdge>();\n @Output() canvasClick = new EventEmitter<Position>();\n @Output() contextMenu = new EventEmitter<ContextMenuEvent>();\n\n private readonly canvasSvgRef = viewChild<ElementRef>('canvasSvg');\n\n // Internal state\n internalGraph = signal<Graph>({ nodes: [], edges: [] });\n selection = signal<SelectionState>({ nodes: [], edges: [] });\n validationResult = signal<ValidationResult | null>(null);\n\n // Pan & Zoom state\n panX = signal(0);\n panY = signal(0);\n scale = signal(1);\n\n // Dragging state\n private draggedNode: GraphNode | null = null;\n private dragOffset: Position = { x: 0, y: 0 };\n private isPanning = false;\n private lastMousePos: Position = { x: 0, y: 0 };\n private draggedEdge: { edge: GraphEdge; endpoint: 'source' | 'target' } | null = null;\n private hoveredNodeId: string | null = null;\n hoveredPort: { nodeId: string; port: 'top' | 'bottom' | 'left' | 'right' } | null = null;\n\n // Attachment points visibility\n showAttachmentPoints = signal<string | null>(null); // nodeId to show ports for\n\n // Active tool\n activeTool = signal<'hand' | 'line'>('hand');\n\n // Line tool state\n private pendingEdge: { sourceId: string; sourcePort: 'top' | 'bottom' | 'left' | 'right' } | null = null;\n\n // Preview line for line tool (rubber-band from source to cursor)\n previewLine = signal<{ source: Position; target: Position } | null>(null);\n\n // Computed\n transform = computed(() =>\n `translate(${this.panX()}, ${this.panY()}) scale(${this.scale()})`\n );\n\n gridBounds = computed(() => {\n const gridSize = this.config.canvas?.grid?.size || 20;\n const viewportWidth = 10000; // Large enough to cover any reasonable viewport\n const viewportHeight = 10000;\n\n // Calculate grid offset to align with pan\n const x = Math.floor(-this.panX() / this.scale() / gridSize) * gridSize - viewportWidth / 2;\n const y = Math.floor(-this.panY() / this.scale() / gridSize) * gridSize - viewportHeight / 2;\n\n return {\n x,\n y,\n width: viewportWidth * 2,\n height: viewportHeight * 2\n };\n });\n\n // Shadow configuration (defaults to true)\n shadowsEnabled = computed(() => this.config.theme?.shadows !== false);\n\n // Selected edge info for direction selector positioning\n selectedEdgeMidpoint = computed(() => {\n const sel = this.selection();\n if (sel.edges.length !== 1) return null;\n const edge = this.internalGraph().edges.find(e => e.id === sel.edges[0]);\n if (!edge) return null;\n\n const sourcePoint = this.getEdgeSourcePoint(edge);\n const targetPoint = this.getEdgeTargetPoint(edge);\n const midX = (sourcePoint.x + targetPoint.x) / 2;\n const midY = (sourcePoint.y + targetPoint.y) / 2;\n\n return {\n edge,\n x: midX * this.scale() + this.panX(),\n y: midY * this.scale() + this.panY()\n };\n });\n\n constructor() {}\n\n ngOnChanges(changes: SimpleChanges) {\n // Sync graph input to internal signal\n if (changes['graph'] && changes['graph'].currentValue) {\n this.internalGraph.set(structuredClone(changes['graph'].currentValue));\n }\n }\n\n ngOnInit() {\n // Initialize with current graph value\n if (this.graph) {\n this.internalGraph.set(structuredClone(this.graph));\n }\n this.validate();\n }\n\n // Node operations\n addNode(type: string, position?: Position): GraphNode {\n const nodeConfig = this.config.nodes.types.find(t => t.type === type);\n if (!nodeConfig) {\n throw new Error(`Unknown node type: ${type}`);\n }\n\n const newNode: GraphNode = {\n id: this.generateId(),\n type,\n data: structuredClone(nodeConfig.defaultData),\n position: position || { x: 100, y: 100 }\n };\n\n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n nodes: [...graph.nodes, newNode]\n });\n\n this.emitGraphChange();\n this.nodeAdded.emit(newNode);\n this.switchTool('hand');\n return newNode;\n }\n\n removeNode(nodeId: string, removeAttachedEdges = false): void {\n const graph = this.internalGraph();\n const removedNode = graph.nodes.find(n => n.id === nodeId);\n this.internalGraph.set({\n ...graph,\n nodes: graph.nodes.filter(n => n.id !== nodeId),\n edges: removeAttachedEdges\n ? graph.edges.filter(e => e.source !== nodeId && e.target !== nodeId)\n : graph.edges\n });\n this.selection.set({ nodes: [], edges: [] });\n this.emitGraphChange();\n if (removedNode) this.nodeRemoved.emit(removedNode);\n }\n\n removeEdge(edgeId: string): void {\n const graph = this.internalGraph();\n const removedEdge = graph.edges.find(e => e.id === edgeId);\n this.internalGraph.set({\n ...graph,\n edges: graph.edges.filter(e => e.id !== edgeId)\n });\n this.selection.set({ nodes: [], edges: [] });\n this.emitGraphChange();\n if (removedEdge) this.edgeRemoved.emit(removedEdge);\n }\n\n updateNode(nodeId: string, updates: Partial<GraphNode>): void {\n const graph = this.internalGraph();\n const nodeIndex = graph.nodes.findIndex(n => n.id === nodeId);\n if (nodeIndex === -1) return;\n\n const updatedNodes = [...graph.nodes];\n updatedNodes[nodeIndex] = { ...updatedNodes[nodeIndex], ...updates };\n\n this.internalGraph.set({\n ...graph,\n nodes: updatedNodes\n });\n this.emitGraphChange();\n }\n\n // Selection\n selectNode(nodeId: string | null): void {\n if (nodeId === null) {\n this.selection.set({ nodes: [], edges: [] });\n } else {\n this.selection.set({ nodes: [nodeId], edges: [] });\n }\n this.selectionChange.emit(this.selection());\n }\n\n selectEdge(edgeId: string | null): void {\n if (edgeId === null) {\n this.selection.set({ nodes: [], edges: [] });\n } else {\n this.selection.set({ nodes: [], edges: [edgeId] });\n }\n this.selectionChange.emit(this.selection());\n }\n\n onKeyDown(event: KeyboardEvent): void {\n if (this.readonly || this.config.interaction?.readonly) return;\n\n // Escape: cancel line drawing, clear selection\n if (event.key === 'Escape') {\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n this.showAttachmentPoints.set(null);\n event.preventDefault();\n return;\n }\n\n if (event.key === 'Delete' || event.key === 'Backspace') {\n const sel = this.selection();\n\n // Delete selected edges\n if (sel.edges.length > 0) {\n for (const edgeId of sel.edges) {\n this.removeEdge(edgeId);\n }\n event.preventDefault();\n return;\n }\n\n // Delete selected nodes (keep attached edges)\n if (sel.nodes.length > 0) {\n for (const nodeId of sel.nodes) {\n this.removeNode(nodeId, false);\n }\n event.preventDefault();\n return;\n }\n }\n\n // Arrow keys: nudge selected node(s) — 1px default, 10px with Shift\n if (event.key.startsWith('Arrow')) {\n const sel = this.selection();\n if (sel.nodes.length === 0) return;\n\n const step = event.shiftKey ? 10 : 1;\n let dx = 0;\n let dy = 0;\n switch (event.key) {\n case 'ArrowUp': dy = -step; break;\n case 'ArrowDown': dy = step; break;\n case 'ArrowLeft': dx = -step; break;\n case 'ArrowRight': dx = step; break;\n }\n\n event.preventDefault();\n\n const graph = this.internalGraph();\n const updatedNodes = [...graph.nodes];\n for (const nodeId of sel.nodes) {\n const idx = updatedNodes.findIndex(n => n.id === nodeId);\n if (idx === -1) continue;\n const pos = updatedNodes[idx].position;\n updatedNodes[idx] = { ...updatedNodes[idx], position: { x: pos.x + dx, y: pos.y + dy } };\n }\n\n // Recalculate edge ports for moved nodes (atomic update)\n const movedIds = new Set(sel.nodes);\n const updatedEdges = graph.edges.map(edge => {\n if (!movedIds.has(edge.source) && !movedIds.has(edge.target)) return edge;\n const sourceNode = updatedNodes.find(n => n.id === edge.source);\n const targetNode = updatedNodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n\n this.internalGraph.set({ ...graph, nodes: updatedNodes, edges: updatedEdges });\n this.emitGraphChange();\n }\n }\n\n switchTool(tool: 'hand' | 'line'): void {\n const previousTool = this.activeTool();\n\n // Cancel any in-progress line drawing\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n\n // Preserve node selection when switching hand → line\n if (!(previousTool === 'hand' && tool === 'line')) {\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n }\n\n this.activeTool.set(tool);\n\n // Hand → line with a node selected: start edge from that node\n if (previousTool === 'hand' && tool === 'line') {\n const sel = this.selection();\n if (sel.nodes.length === 1) {\n this.pendingEdge = { sourceId: sel.nodes[0], sourcePort: 'bottom' };\n }\n }\n }\n\n /** @deprecated Use switchTool('line') instead */\n switchToLineTool(): void {\n this.switchTool('line');\n }\n\n onEdgeClick(event: MouseEvent, edge: GraphEdge): void {\n if (this.activeTool() !== 'hand') return;\n event.stopPropagation();\n this.selectEdge(edge.id);\n this.edgeClick.emit(edge);\n }\n\n onEdgeDoubleClick(event: MouseEvent, edge: GraphEdge): void {\n if (this.activeTool() !== 'hand') return;\n event.stopPropagation();\n this.selectEdge(edge.id);\n this.edgeDoubleClick.emit(edge);\n }\n\n clearSelection(): void {\n this.selection.set({ nodes: [], edges: [] });\n this.selectionChange.emit(this.selection());\n }\n\n // Validation\n validate(): ValidationResult {\n if (!this.config.validation) {\n const result = { valid: true, errors: [] };\n this.validationResult.set(result);\n return result;\n }\n\n const errors = this.config.validation!.validators.flatMap(rule =>\n rule.validator(this.internalGraph(), this.config)\n );\n\n const result = {\n valid: errors.filter(e => e.severity !== 'warning').length === 0,\n errors\n };\n\n this.validationResult.set(result);\n this.validationChange.emit(result);\n return result;\n }\n\n // Layout\n async applyLayout(direction: 'TB' | 'LR' = 'TB'): Promise<void> {\n const graph = this.internalGraph();\n if (graph.nodes.length === 0) return;\n\n // Dynamic import to avoid compile-time module resolution issues\n const dagreModule = await import('dagre');\n const dagre = dagreModule.default ?? dagreModule;\n\n const g = new dagre.graphlib.Graph();\n g.setGraph({\n rankdir: direction,\n nodesep: 60,\n ranksep: 80,\n marginx: 40,\n marginy: 40,\n });\n g.setDefaultEdgeLabel(() => ({}));\n\n for (const node of graph.nodes) {\n const size = this.getNodeSize(node);\n g.setNode(node.id, { width: size.width, height: size.height });\n }\n\n for (const edge of graph.edges) {\n g.setEdge(edge.source, edge.target);\n }\n\n dagre.layout(g);\n\n const updatedNodes = graph.nodes.map(node => {\n const dagreNode = g.node(node.id);\n if (!dagreNode) return node;\n const size = this.getNodeSize(node);\n return {\n ...node,\n position: {\n x: dagreNode.x - size.width / 2,\n y: dagreNode.y - size.height / 2,\n },\n };\n });\n\n this.internalGraph.set({ ...graph, nodes: updatedNodes });\n this.emitGraphChange();\n\n setTimeout(() => this.fitToScreen());\n }\n\n fitToScreen(padding = 40): void {\n const nodes = this.internalGraph().nodes;\n if (nodes.length === 0) return;\n\n // Get SVG element dimensions\n const ref = this.canvasSvgRef();\n const svgEl: SVGSVGElement | null = ref?.nativeElement ?? ref ?? null;\n if (!svgEl || typeof svgEl.getBoundingClientRect !== 'function') return;\n\n const rect = svgEl.getBoundingClientRect();\n const viewW = rect.width;\n const viewH = rect.height;\n if (viewW === 0 || viewH === 0) return;\n\n // Calculate bounding box of all nodes\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const node of nodes) {\n const size = this.getNodeSize(node);\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n const contentW = maxX - minX;\n const contentH = maxY - minY;\n\n // Handle single node or all nodes stacked\n if (contentW <= 0 && contentH <= 0) {\n this.scale.set(1);\n this.panX.set(viewW / 2 - (minX + 110) * 1);\n this.panY.set(viewH / 2 - (minY + 50) * 1);\n return;\n }\n\n // Calculate scale to fit content with padding (cap at 1 to avoid zooming in too much)\n const zoomConfig = this.config.canvas?.zoom;\n const minScale = zoomConfig?.min ?? 0.25;\n const scaleX = contentW > 0 ? (viewW - padding * 2) / contentW : 1;\n const scaleY = contentH > 0 ? (viewH - padding * 2) / contentH : 1;\n const newScale = Math.max(minScale, Math.min(1, Math.min(scaleX, scaleY)));\n\n // Center the content in the viewport\n const centerX = (minX + maxX) / 2;\n const centerY = (minY + maxY) / 2;\n const newPanX = viewW / 2 - centerX * newScale;\n const newPanY = viewH / 2 - centerY * newScale;\n\n this.scale.set(newScale);\n this.panX.set(newPanX);\n this.panY.set(newPanY);\n }\n\n zoomTo(level: number): void {\n const zoomConfig = this.config.canvas?.zoom;\n const min = zoomConfig?.min ?? 0.25;\n const max = zoomConfig?.max ?? 2.0;\n this.scale.set(Math.max(min, Math.min(max, level)));\n }\n\n getSelection(): SelectionState {\n return this.selection();\n }\n\n // Event handlers\n onCanvasMouseDown(event: MouseEvent): void {\n if (this.readonly) return;\n\n // Cancel pending edge on empty space click\n if (this.pendingEdge) {\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n\n const target = event.target as SVGElement;\n const isNode = !!target.closest('.graph-node');\n const isEdgeEndpoint = target.classList.contains('edge-endpoint');\n const isAttachmentPoint = target.classList.contains('attachment-point');\n const isHitArea = target.classList.contains('edge-hit-area');\n const isInteractive = isNode || isEdgeEndpoint || isAttachmentPoint || isHitArea;\n\n if (!isInteractive) {\n this.isPanning = true;\n this.lastMousePos = { x: event.clientX, y: event.clientY };\n this.clearSelection();\n event.preventDefault();\n }\n }\n\n onCanvasMouseMove(event: MouseEvent): void {\n if (this.isPanning) {\n const dx = event.clientX - this.lastMousePos.x;\n const dy = event.clientY - this.lastMousePos.y;\n this.panX.set(this.panX() + dx);\n this.panY.set(this.panY() + dy);\n this.lastMousePos = { x: event.clientX, y: event.clientY };\n } else if (this.draggedNode) {\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n let x = mouseX - this.dragOffset.x;\n let y = mouseY - this.dragOffset.y;\n\n // Smart snap to grid\n if (this.config.canvas?.grid?.snap) {\n const gridSize = this.config.canvas.grid.size || 20;\n const snapThreshold = gridSize / 4;\n\n const snapX = Math.round(x / gridSize) * gridSize;\n const snapY = Math.round(y / gridSize) * gridSize;\n\n if (Math.abs(x - snapX) < snapThreshold) x = snapX;\n if (Math.abs(y - snapY) < snapThreshold) y = snapY;\n }\n\n // Atomic update: node position + edge port recalculation in one graph set\n const graph = this.internalGraph();\n const nodeIndex = graph.nodes.findIndex(n => n.id === this.draggedNode!.id);\n if (nodeIndex !== -1) {\n const updatedNodes = [...graph.nodes];\n updatedNodes[nodeIndex] = { ...updatedNodes[nodeIndex], position: { x, y } };\n\n // Recalculate ports for all edges connected to this node\n const draggedId = this.draggedNode.id;\n const updatedEdges = graph.edges.map(edge => {\n if (edge.source !== draggedId && edge.target !== draggedId) return edge;\n const sourceNode = updatedNodes.find(n => n.id === edge.source);\n const targetNode = updatedNodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n\n this.internalGraph.set({ ...graph, nodes: updatedNodes, edges: updatedEdges });\n this.emitGraphChange();\n }\n } else if (this.draggedEdge) {\n // Edge reconnection - find hovered node and closest port\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n\n // Find node under cursor\n const nodeId = this.findNodeAtPosition({ x: mouseX, y: mouseY });\n\n if (nodeId) {\n // Show attachment points for this node\n this.showAttachmentPoints.set(nodeId);\n\n // Find closest port\n const closestPort = this.findClosestPort(nodeId, { x: mouseX, y: mouseY });\n\n // Highlight port if within snap distance (40px)\n if (closestPort && closestPort.distance < 40) {\n this.hoveredPort = { nodeId, port: closestPort.port };\n this.hoveredNodeId = nodeId;\n } else {\n this.hoveredPort = null;\n this.hoveredNodeId = null;\n }\n } else {\n // No node nearby - hide attachment points\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.hoveredNodeId = null;\n }\n } else if (this.pendingEdge && this.activeTool() === 'line') {\n // Line tool pending state - show rubber-band preview + attachment points on hovered node\n const rect = (event.currentTarget as SVGSVGElement).getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n\n // Get source port position\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePoint = this.getPortWorldPosition(sourceNode, this.pendingEdge.sourcePort);\n\n // Check if cursor is near a node - snap to its closest port\n const hoveredNodeId = this.findNodeAtPosition({ x: mouseX, y: mouseY });\n let targetPoint: Position = { x: mouseX, y: mouseY };\n\n if (hoveredNodeId && hoveredNodeId !== this.pendingEdge.sourceId) {\n // Show attachment points on hovered node\n this.showAttachmentPoints.set(hoveredNodeId);\n\n // Find and highlight closest port\n const closestPort = this.findClosestPort(hoveredNodeId, { x: mouseX, y: mouseY });\n if (closestPort && closestPort.distance < 40) {\n this.hoveredPort = { nodeId: hoveredNodeId, port: closestPort.port };\n // Snap preview line to port\n const hoveredNode = this.internalGraph().nodes.find(n => n.id === hoveredNodeId);\n if (hoveredNode) {\n targetPoint = this.getPortWorldPosition(hoveredNode, closestPort.port);\n }\n } else {\n this.hoveredPort = null;\n }\n } else {\n // Not over a valid target node - hide attachment points\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n }\n\n this.previewLine.set({ source: sourcePoint, target: targetPoint });\n }\n }\n }\n\n onCanvasMouseUp(_event: MouseEvent): void {\n // Handle edge reconnection with port snapping\n if (this.draggedEdge && this.hoveredNodeId && this.hoveredPort) {\n const graph = this.internalGraph();\n const edgeIndex = graph.edges.findIndex(e => e.id === this.draggedEdge!.edge.id);\n\n if (edgeIndex !== -1) {\n const updatedEdges = [...graph.edges];\n const updatedEdge = { ...updatedEdges[edgeIndex] };\n\n // Update node connection and store port information (non-null: guarded by if condition)\n if (this.draggedEdge.endpoint === 'source') {\n updatedEdge.source = this.hoveredNodeId!;\n updatedEdge.sourcePort = this.hoveredPort!.port;\n } else {\n updatedEdge.target = this.hoveredNodeId!;\n updatedEdge.targetPort = this.hoveredPort!.port;\n }\n\n updatedEdges[edgeIndex] = updatedEdge;\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n this.emitGraphChange();\n this.edgeUpdated.emit(updatedEdge);\n }\n }\n\n this.isPanning = false;\n this.draggedNode = null;\n this.draggedEdge = null;\n this.hoveredNodeId = null;\n this.hoveredPort = null;\n this.showAttachmentPoints.set(null);\n }\n\n onNodeMouseDown(event: MouseEvent, node: GraphNode): void {\n if (this.readonly) return;\n event.stopPropagation(); // Always prevent canvas from seeing node mousedowns\n if (this.activeTool() !== 'hand') return;\n\n this.draggedNode = node;\n\n // Calculate offset between mouse position and node origin to prevent jump\n const svg = (event.target as SVGElement).closest('svg')!;\n const rect = svg.getBoundingClientRect();\n const mouseX = (event.clientX - rect.left - this.panX()) / this.scale();\n const mouseY = (event.clientY - rect.top - this.panY()) / this.scale();\n this.dragOffset = {\n x: mouseX - node.position.x,\n y: mouseY - node.position.y\n };\n }\n\n onNodeClick(event: MouseEvent, node: GraphNode): void {\n if (this.activeTool() === 'line') {\n event.stopPropagation();\n\n if (!this.pendingEdge) {\n // First click - start edge from this node\n // Pick initial port based on geometry (will be recalculated on second click)\n this.pendingEdge = { sourceId: node.id, sourcePort: 'bottom' };\n this.selectNode(node.id);\n } else if (this.pendingEdge.sourceId !== node.id) {\n // Second click on different node - complete the edge\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePort = this.findClosestPortForEdge(sourceNode, node, 'source');\n const targetPort = this.findClosestPortForEdge(node, sourceNode, 'target');\n\n const newEdge: GraphEdge = {\n id: `edge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n source: this.pendingEdge.sourceId,\n target: node.id,\n sourcePort,\n targetPort\n };\n\n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n edges: [...graph.edges, newEdge]\n });\n this.emitGraphChange();\n this.edgeAdded.emit(newEdge);\n }\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n } else {\n // Clicked same node - cancel\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n } else {\n // Hand tool - normal select\n this.selectNode(node.id);\n }\n }\n\n onAttachmentPointClick(event: MouseEvent, node: GraphNode, port: 'top' | 'bottom' | 'left' | 'right'): void {\n event.stopPropagation();\n if (this.readonly) return;\n\n if (this.activeTool() === 'line') {\n if (!this.pendingEdge) {\n // First click on attachment point - start edge from this specific port\n this.pendingEdge = { sourceId: node.id, sourcePort: port };\n this.selectNode(node.id);\n } else if (this.pendingEdge.sourceId !== node.id) {\n // Second click - complete edge to this specific port\n const sourceNode = this.internalGraph().nodes.find(n => n.id === this.pendingEdge!.sourceId);\n if (sourceNode) {\n const sourcePort = this.findClosestPortForEdge(sourceNode, node, 'source');\n\n const newEdge: GraphEdge = {\n id: `edge_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n source: this.pendingEdge.sourceId,\n target: node.id,\n sourcePort,\n targetPort: port\n };\n\n const graph = this.internalGraph();\n this.internalGraph.set({\n ...graph,\n edges: [...graph.edges, newEdge]\n });\n this.emitGraphChange();\n this.edgeAdded.emit(newEdge);\n }\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n } else {\n // Clicked same node - cancel\n this.pendingEdge = null;\n this.previewLine.set(null);\n this.showAttachmentPoints.set(null);\n this.hoveredPort = null;\n this.clearSelection();\n }\n }\n }\n\n onEdgeEndpointMouseDown(event: MouseEvent, edge: GraphEdge, endpoint: 'source' | 'target'): void {\n if (this.readonly) return;\n event.stopPropagation();\n this.draggedEdge = { edge, endpoint };\n }\n\n onWheel(event: WheelEvent): void {\n const zoomConfig = this.config.canvas?.zoom;\n if (!zoomConfig?.wheelEnabled) return;\n\n event.preventDefault();\n const delta = -event.deltaY;\n const step = zoomConfig.step ?? 0.1;\n const newScale = Math.max(\n zoomConfig.min ?? 0.25,\n Math.min(\n zoomConfig.max ?? 2.0,\n this.scale() + (delta > 0 ? step : -step)\n )\n );\n\n this.scale.set(newScale);\n }\n\n onContextMenu(event: MouseEvent): void {\n event.preventDefault();\n \n const svgRect = this.canvasSvgRef()?.nativeElement.getBoundingClientRect();\n if (!svgRect) return;\n\n // Calculate position in graph coordinates\n const x = (event.clientX - svgRect.left - this.panX()) / this.scale();\n const y = (event.clientY - svgRect.top - this.panY()) / this.scale();\n\n // Check if clicking on a node\n const nodeId = this.findNodeAtPosition({ x, y });\n if (nodeId) {\n this.contextMenu.emit({\n type: 'node',\n position: { x: event.clientX, y: event.clientY },\n nodeId\n });\n return;\n }\n\n // Check if clicking on an edge (use hit area logic)\n const edgeId = this.findEdgeAtPosition({ x, y });\n if (edgeId) {\n this.contextMenu.emit({\n type: 'edge',\n position: { x: event.clientX, y: event.clientY },\n edgeId\n });\n return;\n }\n\n // Canvas click\n this.contextMenu.emit({\n type: 'canvas',\n position: { x: event.clientX, y: event.clientY }\n });\n }\n\n // Helper methods\n private emitGraphChange(): void {\n this.graphChange.emit(this.internalGraph());\n if (this.config.validation?.validateOnChange) {\n this.validate();\n }\n }\n\n private generateId(): string {\n return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n private recalculateEdgePorts(nodeId: string): void {\n const graph = this.internalGraph();\n let changed = false;\n const updatedEdges = graph.edges.map(edge => {\n if (edge.source !== nodeId && edge.target !== nodeId) return edge;\n\n const sourceNode = graph.nodes.find(n => n.id === edge.source);\n const targetNode = graph.nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return edge;\n\n const newSourcePort = this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const newTargetPort = this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n\n if (edge.sourcePort === newSourcePort && edge.targetPort === newTargetPort) return edge;\n\n changed = true;\n return { ...edge, sourcePort: newSourcePort, targetPort: newTargetPort };\n });\n\n if (changed) {\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n }\n }\n\n getNodeSize(node: GraphNode): { width: number; height: number } {\n const nodeConfig = this.config.nodes.types.find(t => t.type === node.type);\n return nodeConfig?.size || this.config.nodes.defaultSize || { width: 220, height: 100 };\n }\n\n getEdgePath(edge: GraphEdge): string {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n\n if (!sourceNode || !targetNode) return '';\n\n // Get port positions from edge or calculate closest\n const sourcePort = (edge.sourcePort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n const targetPort = (edge.targetPort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n\n const sourcePoint = this.getPortWorldPosition(sourceNode, sourcePort);\n const targetPoint = this.getPortWorldPosition(targetNode, targetPort);\n\n // Simple straight line\n return `M ${sourcePoint.x},${sourcePoint.y} L ${targetPoint.x},${targetPoint.y}`;\n }\n\n getEdgeColor(edge: GraphEdge): string {\n return edge.metadata?.style?.stroke || this.config.edges.style?.stroke || '#94a3b8';\n }\n\n getEdgeMarkerEnd(edge: GraphEdge): string | null {\n const dir = edge.direction || 'forward';\n const selected = this.selection().edges.includes(edge.id);\n if (dir === 'forward' || dir === 'bidirectional') {\n return selected ? 'url(#arrow-end-selected)' : 'url(#arrow-end)';\n }\n return null;\n }\n\n getEdgeMarkerStart(edge: GraphEdge): string | null {\n const dir = edge.direction || 'forward';\n const selected = this.selection().edges.includes(edge.id);\n if (dir === 'backward' || dir === 'bidirectional') {\n return selected ? 'url(#arrow-start-selected)' : 'url(#arrow-start)';\n }\n return null;\n }\n\n setEdgeDirection(direction: 'forward' | 'backward' | 'bidirectional'): void {\n const sel = this.selection();\n if (sel.edges.length !== 1) return;\n\n const graph = this.internalGraph();\n const edgeIndex = graph.edges.findIndex(e => e.id === sel.edges[0]);\n if (edgeIndex === -1) return;\n\n const updatedEdges = [...graph.edges];\n updatedEdges[edgeIndex] = { ...updatedEdges[edgeIndex], direction };\n this.internalGraph.set({ ...graph, edges: updatedEdges });\n this.emitGraphChange();\n this.edgeUpdated.emit(updatedEdges[edgeIndex]);\n }\n\n getEdgeSourcePoint(edge: GraphEdge): Position {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return { x: 0, y: 0 };\n\n const sourcePort = (edge.sourcePort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(sourceNode, targetNode, 'source');\n return this.getPortWorldPosition(sourceNode, sourcePort);\n }\n\n getEdgeTargetPoint(edge: GraphEdge): Position {\n const sourceNode = this.internalGraph().nodes.find(n => n.id === edge.source);\n const targetNode = this.internalGraph().nodes.find(n => n.id === edge.target);\n if (!sourceNode || !targetNode) return { x: 0, y: 0 };\n\n const targetPort = (edge.targetPort as 'top' | 'bottom' | 'left' | 'right') || this.findClosestPortForEdge(targetNode, sourceNode, 'target');\n return this.getPortWorldPosition(targetNode, targetPort);\n }\n\n getNodeTypeIcon(node: GraphNode): string {\n const nodeConfig = this.config.nodes.types.find(t => t.type === node.type);\n return nodeConfig?.icon || '●';\n }\n\n getIconPosition(node: GraphNode): Position {\n const size = this.getNodeSize(node);\n const pos = this.config.nodes.iconPosition || 'top-left';\n const padding = size.height * 0.25;\n const iconSize = size.height * 0.28;\n\n const positions: Record<string, Position> = {\n 'top-left': { x: padding, y: padding },\n 'top': { x: size.width / 2, y: padding },\n 'top-right': { x: size.width - padding, y: padding },\n 'right': { x: size.width - padding, y: size.height / 2 },\n 'bottom-right': { x: size.width - padding, y: size.height - padding },\n 'bottom': { x: size.width / 2, y: size.height - padding },\n 'bottom-left': { x: padding, y: size.height - padding },\n 'left': { x: padding, y: size.height / 2 }\n };\n\n return positions[pos] || positions['left'];\n }\n\n getLabelPosition(node: GraphNode): Position {\n const size = this.getNodeSize(node);\n const pos = this.config.nodes.iconPosition || 'top-left';\n const padding = size.height * 0.25;\n\n // Label position adjusts based on icon position\n const labelPositions: Record<string, Position> = {\n 'top-left': { x: size.width / 2 + padding / 2, y: size.height / 2 + 4 },\n 'top': { x: size.width / 2, y: size.height / 2 + padding / 2 },\n 'top-right': { x: size.width / 2 - padding / 2, y: size.height / 2 + 4 },\n 'right': { x: size.width / 2 - padding / 2, y: size.height / 2 },\n 'bottom-right': { x: size.width / 2 - padding / 2, y: size.height / 2 - 4 },\n 'bottom': { x: size.width / 2, y: size.height / 2 - padding / 2 },\n 'bottom-left': { x: size.width / 2 + padding / 2, y: size.height / 2 - 4 },\n 'left': { x: size.width / 2 + padding / 2, y: size.height / 2 }\n };\n\n return labelPositions[pos] || labelPositions['top-left'];\n }\n\n private findNodeAtPosition(pos: Position): string | null {\n for (const node of this.internalGraph().nodes) {\n const size = this.getNodeSize(node);\n if (\n pos.x >= node.position.x &&\n pos.x <= node.position.x + size.width &&\n pos.y >= node.position.y &&\n pos.y <= node.position.y + size.height\n ) {\n return node.id;\n }\n }\n return null;\n }\n\n private findEdgeAtPosition(pos: Position): string | null {\n const hitDistance = 10; // pixels tolerance\n for (const edge of this.internalGraph().edges) {\n const sourcePoint = this.getEdgeSourcePoint(edge);\n const targetPoint = this.getEdgeTargetPoint(edge);\n \n // Calculate distance from point to line segment\n const dist = this.pointToSegmentDistance(pos, sourcePoint, targetPoint);\n if (dist < hitDistance) {\n return edge.id;\n }\n }\n return null;\n }\n\n private pointToSegmentDistance(point: Position, lineStart: Position, lineEnd: Position): number {\n const dx = lineEnd.x - lineStart.x;\n const dy = lineEnd.y - lineStart.y;\n const lengthSquared = dx * dx + dy * dy;\n \n if (lengthSquared === 0) {\n // Line segment is a point\n return Math.sqrt((point.x - lineStart.x) ** 2 + (point.y - lineStart.y) ** 2);\n }\n \n // Project point onto line segment\n let t = ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / lengthSquared;\n t = Math.max(0, Math.min(1, t));\n \n const projX = lineStart.x + t * dx;\n const projY = lineStart.y + t * dy;\n \n return Math.sqrt((point.x - projX) ** 2 + (point.y - projY) ** 2);\n }\n\n getNodePorts(node: GraphNode): Array<{ position: 'top' | 'bottom' | 'left' | 'right'; x: number; y: number }> {\n const size = this.getNodeSize(node);\n return [\n { position: 'top', x: size.width / 2, y: 0 },\n { position: 'bottom', x: size.width / 2, y: size.height },\n { position: 'left', x: 0, y: size.height / 2 },\n { position: 'right', x: size.width, y: size.height / 2 }\n ];\n }\n\n private findClosestPort(nodeId: string, worldPos: Position): { port: 'top' | 'bottom' | 'left' | 'right'; distance: number } | null {\n const node = this.internalGraph().nodes.find(n => n.id === nodeId);\n if (!node) return null;\n\n const ports = this.getNodePorts(node);\n let closestPort: typeof ports[0] | null = null;\n let minDistance = Infinity;\n\n for (const port of ports) {\n const portWorldX = node.position.x + port.x;\n const portWorldY = node.position.y + port.y;\n const dx = worldPos.x - portWorldX;\n const dy = worldPos.y - portWorldY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance < minDistance) {\n minDistance = distance;\n closestPort = port;\n }\n }\n\n return closestPort ? { port: closestPort.position, distance: minDistance } : null;\n }\n\n private getPortWorldPosition(node: GraphNode, port: 'top' | 'bottom' | 'left' | 'right'): Position {\n const size = this.getNodeSize(node);\n const portOffsets = {\n top: { x: size.width / 2, y: 0 },\n bottom: { x: size.width / 2, y: size.height },\n left: { x: 0, y: size.height / 2 },\n right: { x: size.width, y: size.height / 2 }\n };\n\n const offset = portOffsets[port];\n return {\n x: node.position.x + offset.x,\n y: node.position.y + offset.y\n };\n }\n\n private findClosestPortForEdge(\n node: GraphNode,\n otherNode: GraphNode,\n endpoint: 'source' | 'target'\n ): 'top' | 'bottom' | 'left' | 'right' {\n const size = this.getNodeSize(node);\n const nodeCenter = {\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2\n };\n const otherSize = this.getNodeSize(otherNode);\n const otherCenter = {\n x: otherNode.position.x + otherSize.width / 2,\n y: otherNode.position.y + otherSize.height / 2\n };\n\n const dx = otherCenter.x - nodeCenter.x;\n const dy = otherCenter.y - nodeCenter.y;\n\n // Determine which port is closest based on relative position\n const absDx = Math.abs(dx);\n const absDy = Math.abs(dy);\n\n if (absDx > absDy) {\n // Horizontal connection\n return dx > 0 ? 'right' : 'left';\n } else {\n // Vertical connection\n return dy > 0 ? 'bottom' : 'top';\n }\n }\n}\n","// Main component\nexport { GraphEditorComponent } from './lib/graph-editor.component';\n\n// Data model - use 'export type' for re-exports when isolatedModules is enabled\nexport type {\n Graph,\n GraphNode,\n GraphEdge,\n Position,\n NodeMetadata,\n EdgeMetadata,\n EdgeStyle,\n GraphMetadata\n} from './lib/graph.model';\n\n// Configuration - use 'export type' for re-exports\nexport type {\n GraphEditorConfig,\n NodesConfig,\n EdgesConfig,\n CanvasConfig,\n ValidationConfig,\n LayoutConfig,\n InteractionConfig,\n ThemeConfig,\n PaletteConfig,\n NodeTypeDefinition,\n PortConfig,\n PortDefinition,\n NodeConstraints,\n GridConfig,\n ZoomConfig,\n PanConfig,\n ValidationRule,\n ValidationError,\n LayoutOptions,\n ContextMenuConfig,\n ContextMenuItem,\n ContextMenuContext,\n SelectionState,\n ValidationResult,\n ContextMenuEvent\n} from './lib/graph-editor.config';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { EventEmitter,
|
|
2
|
-
import { Graph,
|
|
3
|
-
import { GraphEditorConfig, SelectionState, ValidationResult
|
|
1
|
+
import { EventEmitter, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { Graph, GraphEdge, GraphNode, Position } from './graph.model';
|
|
3
|
+
import { ContextMenuEvent, GraphEditorConfig, SelectionState, ValidationResult } from './graph-editor.config';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
/**
|
|
6
6
|
* Main graph editor component.
|
|
@@ -64,6 +64,7 @@ export declare class GraphEditorComponent implements OnInit, OnChanges {
|
|
|
64
64
|
width: number;
|
|
65
65
|
height: number;
|
|
66
66
|
}>;
|
|
67
|
+
shadowsEnabled: import("@angular/core").Signal<boolean>;
|
|
67
68
|
selectedEdgeMidpoint: import("@angular/core").Signal<{
|
|
68
69
|
edge: GraphEdge;
|
|
69
70
|
x: number;
|
|
@@ -114,7 +115,11 @@ export declare class GraphEditorComponent implements OnInit, OnChanges {
|
|
|
114
115
|
getEdgeSourcePoint(edge: GraphEdge): Position;
|
|
115
116
|
getEdgeTargetPoint(edge: GraphEdge): Position;
|
|
116
117
|
getNodeTypeIcon(node: GraphNode): string;
|
|
118
|
+
getIconPosition(node: GraphNode): Position;
|
|
119
|
+
getLabelPosition(node: GraphNode): Position;
|
|
117
120
|
private findNodeAtPosition;
|
|
121
|
+
private findEdgeAtPosition;
|
|
122
|
+
private pointToSegmentDistance;
|
|
118
123
|
getNodePorts(node: GraphNode): Array<{
|
|
119
124
|
position: 'top' | 'bottom' | 'left' | 'right';
|
|
120
125
|
x: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Type } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { EdgeStyle, Graph, Position } from './graph.model';
|
|
3
3
|
export interface GraphEditorConfig {
|
|
4
4
|
/** Node type definitions */
|
|
5
5
|
nodes: NodesConfig;
|
|
@@ -28,6 +28,8 @@ export interface NodesConfig {
|
|
|
28
28
|
height: number;
|
|
29
29
|
};
|
|
30
30
|
constrainToBounds?: boolean;
|
|
31
|
+
/** Icon position within the node (default: 'top-left') */
|
|
32
|
+
iconPosition?: 'top-left' | 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left';
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* Node type definition.
|
|
@@ -192,6 +194,8 @@ export interface ContextMenuContext {
|
|
|
192
194
|
export interface ThemeConfig {
|
|
193
195
|
/** CSS custom property values */
|
|
194
196
|
variables?: Record<string, string>;
|
|
197
|
+
/** Enable drop shadows on nodes and edges (default: true) */
|
|
198
|
+
shadows?: boolean;
|
|
195
199
|
}
|
|
196
200
|
/**
|
|
197
201
|
* Palette configuration.
|